# PromptInput
A growing message composer with attachments, tools, a model picker and a send button that stops a streaming reply.
```ehtml Example
import {
PromptInput, PromptInputTools, PromptInputButton, PromptInputSubmit, PromptInputActionMenu,
PromptInputActionAddAttachments, PromptInputSelect,
} from "@elements/ui/prompt-input";
import { Icon } from "@elements/ui/icon";
send(chat, m)}>
Search
stop(chat)} />
```
## Parts
| Part | What it is |
|---|---|
| `PromptInput` | The form: hidden file input, the box, a header of attachment chips, the textarea, and the footer (default slot). |
| `.prompt-input-textarea` | Grows from minRows to maxRows. Enter submits, Shift+Enter breaks a line, paste attaches files, Backspace on empty removes the last chip. |
| `.prompt-input-header` | Attachment and source chips, then slot header. |
| `PromptInputTools` | A row of tool buttons on the left of the footer. |
| `PromptInputButton` | A ghost tool button with an optional tooltip, shortcut hint and toggle. |
| `PromptInputSubmit` | Send. Its icon follows status; with onStop it stops a reply in flight. |
| `PromptInputActionMenu` | The + menu (a DropdownMenu opening upward). |
| `PromptInputActionMenuItem` | A plain item in the + menu. |
| `PromptInputActionAddAttachments` | Add photos or files: opens the file dialog. |
| `PromptInputActionAddScreenshot` | Take screenshot: captures one frame of a screen the user picks. |
| `PromptInputSelect` | A quiet NativeSelect for the model. |
| `PromptInputSpeechButton` | Dictation into the textarea with the Web Speech API; disabled where unsupported. |
| `PromptInputTabsList / Tab / TabLabel / TabBody / TabItem` | Labelled sections of suggestions, for a hover card or popover. |
| `.prompt-input-drop` | The Drop files to attach overlay while dragging files over the box. |
## Attributes
### PromptInput
| Attribute | Type | Default | Description |
|---|---|---|---|
| `value` | `string` (two-way) | `""` | The text. |
| `files` | `AttachmentData[]` (two-way) | `[]` | Attached files: { id, filename, mediaType, url (blob), size, file }. |
| `sources` | `AttachmentData[]` (two-way) | `[]` | Referenced source documents, shown as chips and sent with the message. |
| `placeholder` | `string` | `"What would you like to know?"` | Textarea placeholder. |
| `label` | `string` | `"Message"` | The textarea's accessible name. |
| `name` | `string` | `"message"` | The textarea's name. |
| `minRows` | `number` | `2` | Minimum height in lines. |
| `maxRows` | `number` | `8` | The height where it stops growing and scrolls. |
| `accept` | `string` | `""` | Accepted files: image/\*, application/pdf, .md. Empty accepts all. |
| `multiple` | `boolean` | `false` | The file dialog takes several files. |
| `globalDrop` | `boolean` | `false` | Accept file drops anywhere on the page. |
| `maxFiles` | `number` | `0` | Most files attached at once; 0 is no limit. |
| `maxFileSize` | `number` | `0` | Largest file in bytes; 0 is no limit. |
| `submitOnEnter` | `boolean` | `true` | Enter submits; Shift+Enter breaks a line. |
| `allowEmpty` | `boolean` | `false` | Submit with no text, files or sources. |
| `disabled` | `boolean` | `false` | Disables the textarea and every control in the box. |
| `autofocus` | `boolean` | `false` | Focus the textarea when it mounts. |
| `onSubmit` | `(message: { text, files, sources }, e: SubmitEvent) => void \| Promise` | `() => {}` | Called on submit, with each file's blob url converted to a data url (the File stays attached). Clears when it returns or resolves; keeps everything when it throws or rejects. |
| `onError` | `(err: { code: "max_files" \| "max_file_size" \| "accept", message: string }) => void` | `() => {}` | A file was refused. |
| `class` | `string` | `""` | Extra classes on the form. |
| `attrs` | `Record` | `{}` | Other attributes for the form. |
| `textareaAttrs` | `Record` | `{}` | Attributes for the textarea: maxlength, aria-describedby, autocomplete. |
| `onTextareaKeyDown` | `(e: KeyboardEvent) => void` | `() => {}` | Runs before the built-in keys; preventDefault skips Enter to submit. |
### PromptInputActionMenu
| Attribute | Type | Default | Description |
|---|---|---|---|
| `icon` | `IconName` | `"plus"` | The trigger's icon (PromptInputActionMenuTrigger children). |
| `label` | `string` | `"Add"` | The + button's and the menu's name. |
| `open` | `boolean` (two-way) | `false` | Whether the menu is open. |
### PromptInputSubmit
| Attribute | Type | Default | Description |
|---|---|---|---|
| `status` | `"ready" \| "submitted" \| "streaming" \| "error"` | `"ready"` | The chat status: enter, spinner, stop square or x. |
| `onStop` | `(() => void) \| undefined` | `undefined` | Set it and the button stops while submitted or streaming. |
| `disabled` | `boolean` | `false` | Not clickable; Enter does not submit either. |
| `variant` | `ButtonVariant` | `"primary"` | Button variant. |
| `label` | `string` | `""` | Overrides Submit / Stop. |
| `size` | `"xs" \| "sm" \| "md" \| "lg"` | `"sm"` | Icon button size. |
| `onclick` | `(e: MouseEvent) => void` | `() => {}` | Runs before the submit when not stopping; e.preventDefault() cancels the send. |
### PromptInputButton
| Attribute | Type | Default | Description |
|---|---|---|---|
| `label` | `string` | `""` | Accessible name; required for icon-only buttons without a tooltip. |
| `tooltip` | `string` | `""` | Shown on hover and focus. |
| `shortcut` | `string` | `""` | A key hint after the tooltip text. |
| `tooltipSide` | `"top" \| "right" \| "bottom" \| "left"` | `"top"` | Tooltip side. |
| `icon` | `boolean` | `false` | Square, icon only. |
| `toggle` | `boolean` | `false` | A toggle button (aria-pressed). |
| `pressed` | `boolean` (two-way) | `false` | Whether the toggle is on. |
| `variant` | `ButtonVariant` | `"ghost"` | Button variant. |
| `onclick` | `(e: MouseEvent) => void` | `() => {}` | Click handler. |
### PromptInputActionAddAttachments
| Attribute | Type | Default | Description |
|---|---|---|---|
| `label` | `string` | `"Add photos or files"` | Item text. |
### PromptInputActionAddScreenshot
| Attribute | Type | Default | Description |
|---|---|---|---|
| `label` | `string` | `"Take screenshot"` | Item text. |
| `onSelect` | `(e: Event) => void` | `() => {}` | Runs first; preventDefault skips the capture. |
### PromptInputSelect
| Attribute | Type | Default | Description |
|---|---|---|---|
| `value` | `string` (two-way) | `""` | The chosen option. |
| `options` | `NativeSelectOptionData[]` | `[]` | { value, label, group?, disabled? }. |
| `label` | `string` | `"Model"` | Accessible name. |
### PromptInputSpeechButton
| Attribute | Type | Default | Description |
|---|---|---|---|
| `lang` | `string` | `""` | Recognition language; defaults to the page's lang. |
| `label` | `string` | `"Voice input"` | Accessible name. |
## Slots
| Slot | Part | Content |
|---|---|---|
| `default` | `PromptInput` | The footer: PromptInputTools on the left, PromptInputSubmit on the right. |
| `header` | `PromptInput` | Extra content after the attachment chips. |
| `default` | `PromptInputButton` | Icon and text. |
| `default` | `PromptInputSubmit` | A custom icon in place of the status icon. |
| `default` | `PromptInputActionMenu` | Menu items. |
## Keyboard
| Keys | Action |
|---|---|
| `Enter` | Submits. Not during IME composition, not while submit is disabled, and not while a reply is generating. |
| `Shift + Enter` | Inserts a line break. |
| `Backspace` | In an empty textarea, removes the last attachment. |
| `Ctrl / Cmd + V` | Pasting files attaches them. |
| `Tab` | Attachment chips and header content, then the textarea, then tools and submit (DOM order). |
| `Escape` | Closes an open menu, tooltip or preview. |
## Data attributes
| Attribute | Values | On | Description |
|---|---|---|---|
| `data-dragging` | present | .prompt-input-box | Files are being dragged over it. |
| `data-pending` | present | .prompt-input-box | An async onSubmit is running. |
| `data-disabled` | present | .prompt-input | |
| `data-status` | `"ready" \| "submitted" \| "streaming" \| "error"` | .prompt-input-submit | |
| `data-state` | `"on" \| "off"` | .prompt-input-button (toggle) | |
| `data-listening` | present | .prompt-input-speech | |
## Accessibility
- The textarea is named by label (Message). The file input is hidden from the tab order and named Upload files.
- Submit is named Submit, or Stop while a reply is submitted or streaming, and sets aria-busy while submitted.
- Attachments are a list of chips; each remove button is named Remove `` and returns focus to the textarea.
- Tool buttons carry aria-label and aria-pressed; tooltips describe them.
- Disabled uses a disabled fieldset, so every control inside is disabled natively, and the box takes no dropped, pasted or chosen files.
- File errors go to onError; the caller decides how to show them (a toast, a field message).
## See also
- [Icon](icon): An inline stroke icon from the set the templates draw their own controls with, sized in pixels and colored by the text around it.
- [Message](message): One chat message with avatar, author, time, streaming Markdown, attachments, actions and response branches.
- [MessageList](message-list): A conversation that stays pinned to the newest message unless the reader scrolls up.
- [Attachment](attachment): A file or source as a thumbnail, chip or row, with preview, size, upload progress and remove.