Pill composerPro
A compact pill that opens into the full composer when it gets focus, growing out of the pill's own shape, and folds back with the draft kept.
On this page
Installation
Usage
import { PillComposer } from "@/components/ui/chatcn/pro/pill-composer"
<PillComposer
placeholder="Ask about this trip…"
status={status}
onStop={stop}
onSubmit={({ text }) => send(text)}
tools={<PromptInputAttachButton />}
/>The open composer is laid out at full size all the time; closed, a clip path cuts it down to the pill. Opening animates that clip from the pill's rectangle and full radius to the card's, while the pill's words glide to where the caret lands, so it reads as one object growing rather than two swapping. Only the pill's 44 px are reserved: with anchor="bottom" the composer grows upward over the thread, with top it grows down. Closing keeps the draft and shows it in the pill. While a reply streams the pill says so and carries the Stop button. Everything else is the free PromptInput: IME safe Enter, autosize, paste and drop, the same props.
Examples
States
Props
| Prop | Type | Notes |
|---|---|---|
value, defaultValue, onValueChange | string | The draft, controlled or not |
onSubmit | ({ text }) => void | Enter or Send. Never while empty, disabled or busy |
status, onStop | "idle" | "submitting" | "streaming", () => void | Send becomes Stop in the same footprint |
disabled | boolean | |
open, defaultOpen, onOpenChange | boolean | Focus on the pill opens it |
anchor | "bottom" | "top" | The edge it grows from. Default bottom |
align | "center" | "start" | Where the pill sits. Default center |
pillWidth | string | Default min(100%, 20rem) |
tools, actions, attachments | ReactNode | Toolbar start, before Send, above the text |
hotkey | string | null | Opens it from anywhere. Default / |
icon | ReactNode | Leading icon in the pill |
labels | Partial<PillComposerLabels> | Every string, for translation |
| ... | PromptInputProps | onFiles, accept, submitOn and the rest pass through |
Keyboard
| Key | Action |
|---|---|
| Tab to the pill | Opens the composer and moves focus into it |
| / | Opens the composer from anywhere outside a text field |
| Enter, Shift Enter | Send, new line. Never sends while an IME is composing |
| Escape | Stops a streaming reply first, then folds the composer back, keeping the draft |
Accessibility
- The pill is a button with
aria-expanded; its name includes the kept draft. - While closed the composer is
inert, so nothing hidden is reachable. - Closing with Escape hands focus back to the pill without reopening it.
- Menus and popovers opened from the toolbar count as inside, so using them never folds the composer.
Motion
The outline morphs in 280 ms and folds back in 210 ms on the kit's ease out, animating only clip-path; contents fade in 200 ms after a 60 ms beat. The edge and shadow are a drop shadow on the clipped shape, so they follow the morph. Reduced motion snaps the outline and keeps the fades.