Prompt Composer
The prompt box of an AI product: it grows with the text, Enter sends, send becomes Stop while the reply streams, and files sit above it.
It owns no model, files or voice. The + button calls onAttach, the mic onVoice, and the model picker and the like go beside it, in actions or in a row under the box. The ember light sweeps the border once, shortly after the box appears, then rests; focus draws a soft ember border in. Enter sends and Shift+Enter breaks the line.
Basic
Type something and press Enter: the send button turns into Stop for three seconds, as if the reply were streaming.
With attachments
Pass AttachmentChips as attachments and they sit above the field.
Props
| Prop | Type | Default | Description |
|---|---|---|---|
| value | string | Controlled value. | |
| defaultValue | string | Initial value when uncontrolled. | |
| onValueChange | (value: string) => void | Called as the text changes. | |
| placeholder | string | Placeholder text. | |
| status | 'idle' | 'streaming' | 'idle' | While streaming, the send button becomes Stop. |
| onSubmit | (value: string) => void | Enter, or the send button. Receives the trimmed text. | |
| onStop | () => void | The Stop button. | |
| onAttach | () => void | The + button. Pass it to show the button. | |
| onVoice | () => void | The mic. Hidden when there is no handler. | |
| attachments | ReactNode | Chips above the field, usually AttachmentChip. | |
| actions | ReactNode | Extra controls on the left, after the +. | |
| maxRows | number | 8 | The most lines the field grows to before it scrolls. |
| glow | 'once' | 'pulse' | 'focus' | 'off' | 'once' | The ember light round the border: one lap shortly after it appears, then still (once); every 2.5s while idle (pulse); one lap on each focus (focus); none (off). |
| disabled | boolean | Disables the field and the buttons. | |
| autoFocus | boolean | Focus the field on mount. | |
| aria-label | string | Accessible name of the field. | |
| className | string | Extra class on the root. |