Components / AI
Prompt Input
A fully-featured AI chat input. Extends ai-elements PromptInput with rectangular styling and built-in speech recognition. Integrates with the Vercel AI SDK useChat hook.
Installation
bash
npx shadcn add https://raw.githubusercontent.com/levi-putna/elements/main/registry/prompt-input/registry.jsonUsage
The component is fully composable. Build the input by assembling sub-components inside PromptInput.
tsx
import {
PromptInput,
PromptInputTextarea,
PromptInputFooter,
PromptInputTools,
PromptInputActionMenu,
PromptInputActionMenuTrigger,
PromptInputActionMenuContent,
PromptInputActionAddAttachments,
PromptInputActionAddScreenshot,
PromptInputSpeech,
PromptInputSubmit,
} from "@/components/ui/prompt-input"
export function Example() {
return (
<PromptInput onSubmit={({ text, files }) => console.log(text, files)}>
<PromptInputTextarea />
<PromptInputFooter>
<PromptInputTools>
<PromptInputActionMenu>
<PromptInputActionMenuTrigger />
<PromptInputActionMenuContent>
<PromptInputActionAddAttachments />
<PromptInputActionAddScreenshot />
</PromptInputActionMenuContent>
</PromptInputActionMenu>
<PromptInputSpeech />
</PromptInputTools>
<PromptInputSubmit />
</PromptInputFooter>
</PromptInput>
)
}Examples
With AI SDK status
Pass status and onStop to PromptInputSubmit to get automatic icon changes and stop behaviour during streaming.
tsx
import { useChat } from "ai/react"
export function Chat() {
const { input, handleInputChange, handleSubmit, status, stop } = useChat()
return (
<PromptInput
onSubmit={({ text }) => handleSubmit()}
value={input}
onChange={handleInputChange}
>
<PromptInputTextarea />
<PromptInputFooter>
<PromptInputTools>
<PromptInputSpeech />
</PromptInputTools>
<PromptInputSubmit status={status} onStop={stop} />
</PromptInputFooter>
</PromptInput>
)
}With model selector
Add PromptInputSelect to the toolbar to let users choose between models.
tsx
<PromptInput onSubmit={handleSubmit}>
<PromptInputFooter>
<PromptInputTools>
<PromptInputSelect value={model} onValueChange={setModel}>
<PromptInputSelectTrigger>
<PromptInputSelectValue />
</PromptInputSelectTrigger>
<PromptInputSelectContent>
<PromptInputSelectItem value="gpt-4o">GPT-4o</PromptInputSelectItem>
<PromptInputSelectItem value="claude-sonnet-4-6">Claude Sonnet</PromptInputSelectItem>
</PromptInputSelectContent>
</PromptInputSelect>
</PromptInputTools>
<PromptInputSubmit />
</PromptInputFooter>
</PromptInput>Features
All features inherited from ai-elements plus additions.
Auto-resizing textareaGrows with content up to max-height, then scrolls.
File attachmentsDrag-and-drop, paste from clipboard, or file picker. Validates type, size, and count.
Screenshot captureUses getDisplayMedia to capture a screen region and attach it as a PNG.
Speech recognitionWeb Speech API. Appends transcript to existing input. Shows mic/mic-off icon. Hides if unsupported.
Model selectorSelect dropdown styled to match the input toolbar.
Action menuPlus-icon dropdown for extensible actions.
AI SDK statusSubmit button adapts: idle → send arrow, submitted → spinner, streaming → stop square.
Keyboard shortcutsEnter to submit, Shift+Enter for newline, Backspace on empty removes last attachment.
PromptInput Props
| Prop | Type | Default | Description |
|---|---|---|---|
| onSubmit | (message: { text: string; files: FileUIPart[] }, event) => void | - | Called when the form is submitted. Receives the text and any attached files. |
| accept | string | - | File type filter passed to the hidden file input. e.g. "image/*" |
| multiple | boolean | true | Allow multiple file attachments. |
| globalDrop | boolean | false | Accept file drops anywhere on the document, not just on the form. |
| maxFiles | number | - | Maximum number of files that can be attached. |
| maxFileSize | number | - | Maximum file size in bytes. |
| onError | (err: { code, message }) => void | - | Called when a file validation constraint is violated. |
PromptInputSubmit Props
| Prop | Type | Default | Description |
|---|---|---|---|
| status | "idle" | "submitted" | "streaming" | "error" | - | AI SDK chat status. Controls the submit button icon: idle → arrow, submitted → spinner, streaming → stop square. |
| onStop | () => void | - | Called when the stop button is clicked during streaming. |
PromptInputSpeech Props
| Prop | Type | Default | Description |
|---|---|---|---|
| onTranscript | (text: string) => void | - | Called with the transcript text after recognition completes. Text is also automatically appended to the textarea value. |