Elements

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.json

Usage

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

PropTypeDefaultDescription
onSubmit(message: { text: string; files: FileUIPart[] }, event) => void-Called when the form is submitted. Receives the text and any attached files.
acceptstring-File type filter passed to the hidden file input. e.g. "image/*"
multiplebooleantrueAllow multiple file attachments.
globalDropbooleanfalseAccept file drops anywhere on the document, not just on the form.
maxFilesnumber-Maximum number of files that can be attached.
maxFileSizenumber-Maximum file size in bytes.
onError(err: { code, message }) => void-Called when a file validation constraint is violated.

PromptInputSubmit Props

PropTypeDefaultDescription
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

PropTypeDefaultDescription
onTranscript(text: string) => void-Called with the transcript text after recognition completes. Text is also automatically appended to the textarea value.