Components
InputBar
The auto-growing iMessage composer: pill textarea + spring-loaded send button. Enter sends (IME-safe, Shift+Enter for newlines), and it deliberately never steals focus — programmatic focus is what causes iOS Safari's keyboard bounce.
"use client";
import { useState } from "react";
import { InputBar, ChatBubble, IMessageScreen } from "imessage-ui";
export default function InputBarDemo() {
const [draft, setDraft] = useState("");
const [sent, setSent] = useState<string[]>([]);
return (
<IMessageScreen className="w-full max-w-sm rounded-2xl p-4">
<ChatBubble variant="received" text="try sending something" senderName="Riley" avatar={{ initial: "R", gradient: ["#FF9FB2", "#E0506E"] }} />
{sent.map((text, i) => (
<ChatBubble key={i} variant="sent" text={text} isNewlySent={i === sent.length - 1} />
))}
{/* `embedded` keeps the bar in flow; Enter sends, Shift+Enter breaks. */}
<div className="mt-3">
<InputBar
embedded
value={draft}
onChange={setDraft}
onSend={text => {
setSent(prev => [...prev, text]);
setDraft("");
}}
/>
</div>
</IMessageScreen>
);
}Usage
import { InputBar } from "imessage-ui";
<InputBar embedded value={draft} onChange={setDraft} onSend={send} />Examples
Emphasis
"use client";
import { useState } from "react";
import { InputBar, IMessageScreen } from "imessage-ui";
/**
* `emphasis` draws attention to the pill: "awaiting" is a subtle border tint
* (the conversation is paused on the user), "highlight" is a golden glow for
* a question aimed directly at them.
*/
export default function EmphasisDemo() {
const [awaiting, setAwaiting] = useState("");
const [highlight, setHighlight] = useState("");
return (
<IMessageScreen className="flex w-full max-w-sm flex-col gap-3 rounded-2xl p-4">
<InputBar
embedded
emphasis="awaiting"
placeholder="Riley is waiting on you…"
value={awaiting}
onChange={setAwaiting}
onSend={() => setAwaiting("")}
/>
<InputBar
embedded
emphasis="highlight"
placeholder="This one's for you specifically"
value={highlight}
onChange={setHighlight}
onSend={() => setHighlight("")}
/>
</IMessageScreen>
);
}Liquid Glass
"use client";
import { useState } from "react";
import { InputBar, IMessageScreen } from "imessage-ui";
/** iOS 26 Liquid Glass styling with the leading "+" attachment button. */
export default function GlassInputDemo() {
const [draft, setDraft] = useState("");
return (
<IMessageScreen
variant="glass"
wallpaper="/memorymap/images/memorymap-12.jpg"
className="flex w-full max-w-sm flex-col justify-end overflow-hidden rounded-2xl p-4 pt-16"
>
<InputBar
embedded
glass
onPlus={() => {}}
value={draft}
onChange={setDraft}
onSend={() => setDraft("")}
/>
</IMessageScreen>
);
}glass restyles the pill as iOS 26 glass; onPlus adds the leading attachment button.
API reference
| Prop | Type | Default | Description |
|---|---|---|---|
| value* | string | — | Controlled draft value. |
| onChange* | (next: string) => void | — | Draft updates. |
| onSend* | (text: string) => void | — | Called with the trimmed draft on send. |
| placeholder | string | "iMessage" | Pill placeholder. |
| disabled | boolean | false | Disable input + send. |
| emphasis | "awaiting" | "highlight" | — | Attention states: subtle border tint vs golden glow. Purely visual — pair with a matching placeholder. |
| submitOnEnter | boolean | true | Enter sends (skips IME composition); Shift+Enter inserts a newline. |
| embedded | boolean | false | Normal flow instead of the keyboard-tracked full-screen footer. |
| glass | boolean | false | iOS 26 Liquid Glass pill styling. |
| onPlus | () => void | — | Renders the leading "+" capsule (glass mode only). |
| onFocus / onBlur | () => void | — | Focus notifications (e.g. snap-scroll to bottom). |
Accessibility
The textarea is labelled "Message", the send button "Send message"; send stays disabled until the trimmed draft has content.