📄 ai-sdk/elements/components/prompt-input

File: prompt-input.md | Updated: 11/15/2025

Source: https://ai-sdk.dev/elements/components/prompt-input

Vercel

Slash Forward

Sparkles

AI SDK

Docs Cookbook Providers Playground AI ElementsAI ElementsLeft sparkleRight sparkle AI GatewayGateway

Search...⌘KFeedback GitHub Vercel LogoSign in with Vercel

Chatbot

Prompt Input

Allows a user to send a message with file attachments to a large language model. It includes a textarea, file upload capabilities, a submit button, and a dropdown for selecting the model.

The PromptInput component allows a user to send a message with file attachments to a large language model. It includes a textarea, file upload capabilities, a submit button, and a dropdown for selecting the model.

Preview

Code

Searchopenai logoGPT-4o

Installation


AI Elements

shadcn CLI

Manual

npx ai-elements@latest add prompt-input

Usage with AI SDK


Build a fully functional chat app using PromptInput, Conversation with a model picker:

Add the following component to your frontend:

app/page.tsx

'use client';

import {
  PromptInput,
  PromptInputActionAddAttachments,
  PromptInputActionMenu,
  PromptInputActionMenuContent,
  PromptInputActionMenuTrigger,
  PromptInputAttachment,
  PromptInputAttachments,
  PromptInputBody,
  PromptInputButton,
  type PromptInputMessage,
  PromptInputSelect,
  PromptInputSelectContent,
  PromptInputSelectItem,
  PromptInputSelectTrigger,
  PromptInputSelectValue,
  PromptInputSpeechButton,
  PromptInputSubmit,
  PromptInputTextarea,
  PromptInputFooter,
  PromptInputTools,
} from '@/components/ai-elements/prompt-input';
import { GlobeIcon } from 'lucide-react';
import { useRef, useState } from 'react';
import { useChat } from '@ai-sdk/react';
import {
  Conversation,
  ConversationContent,
  ConversationScrollButton,
} from '@/components/ai-elements/conversation';
import { Message, MessageContent, MessageResponse } from '@/components/ai-elements/message';

const models = [\
  { id: 'gpt-4o', name: 'GPT-4o' },\
  { id: 'claude-opus-4-20250514', name: 'Claude 4 Opus' },\
];

const InputDemo = () => {
  const [text, setText] = useState<string>('');
  const [model, setModel] = useState<string>(models[0].id);
  const [useWebSearch, setUseWebSearch] = useState<boolean>(false);
  const textareaRef = useRef<HTMLTextAreaElement>(null);

  const { messages, status, sendMessage } = useChat();

  const handleSubmit = (message: PromptInputMessage) => {
    const hasText = Boolean(message.text);
    const hasAttachments = Boolean(message.files?.length);

    if (!(hasText || hasAttachments)) {
      return;
    }

    sendMessage(
      { 
        text: message.text || 'Sent with attachments',
        files: message.files 
      },
      {
        body: {
          model: model,
          webSearch: useWebSearch,
        },
      },
    );
    setText('');
  };

  return (
    <div className="max-w-4xl mx-auto p-6 relative size-full rounded-lg border h-[600px]">
      <div className="flex flex-col h-full">
        <Conversation>
          <ConversationContent>
            {messages.map((message) => (
              <Message from={message.role} key={message.id}>
                <MessageContent>
                  {message.parts.map((part, i) => {
                    switch (part.type) {
                      case 'text':
                        return (
                          <MessageResponse key={`${message.id}-${i}`}>
                            {part.text}
                          </MessageResponse>
                        );
                      default:
                        return null;
                    }
                  })}
                </MessageContent>
              </Message>
            ))}
          </ConversationContent>
          <ConversationScrollButton />
        </Conversation>

        <PromptInput onSubmit={handleSubmit} className="mt-4" globalDrop multiple>
          <PromptInputHeader>
            <PromptInputAttachments>
              {(attachment) => <PromptInputAttachment data={attachment} />}
            </PromptInputAttachments>
          </PromptInputHeader>
          <PromptInputBody>
     
            <PromptInputTextarea
              onChange={(e) => setText(e.target.value)}
              ref={textareaRef}
              value={text}
            />
          </PromptInputBody>
          <PromptInputFooter>
            <PromptInputTools>
              <PromptInputActionMenu>
                <PromptInputActionMenuTrigger />
                <PromptInputActionMenuContent>
                  <PromptInputActionAddAttachments />
                </PromptInputActionMenuContent>
              </PromptInputActionMenu>
              <PromptInputSpeechButton
                onTranscriptionChange={setText}
                textareaRef={textareaRef}
              />
              <PromptInputButton
                onClick={() => setUseWebSearch(!useWebSearch)}
                variant={useWebSearch ? 'default' : 'ghost'}
              >
                <GlobeIcon size={16} />
                <span>Search</span>
              </PromptInputButton>
              <PromptInputSelect
                onValueChange={(value) => {
                  setModel(value);
                }}
                value={model}
              >
                <PromptInputSelectTrigger>
                  <PromptInputSelectValue />
                </PromptInputSelectTrigger>
                <PromptInputSelectContent>
                  {models.map((model) => (
                    <PromptInputSelectItem key={model.id} value={model.id}>
                      {model.name}
                    </PromptInputSelectItem>
                  ))}
                </PromptInputSelectContent>
              </PromptInputSelect>
            </PromptInputTools>
            <PromptInputSubmit disabled={!text && !status} status={status} />
          </PromptInputFooter>
        </PromptInput>
      </div>
    </div>
  );
};

export default InputDemo;

Add the following route to your backend:

app/api/chat/route.ts

import { streamText, UIMessage, convertToModelMessages } from 'ai';

// Allow streaming responses up to 30 seconds
export const maxDuration = 30;

export async function POST(req: Request) {
  const { 
    model, 
    messages, 
    webSearch 
  }: { 
    messages: UIMessage[]; 
    model: string;
    webSearch?: boolean;
  } = await req.json();

  const result = streamText({
    model: webSearch ? 'perplexity/sonar' : model,
    messages: convertToModelMessages(messages),
  });

  return result.toUIMessageStreamResponse();
}

Features


  • Auto-resizing textarea that adjusts height based on content
  • File attachment support with drag-and-drop
  • Image preview for image attachments
  • Configurable file constraints (max files, max size, accepted types)
  • Automatic submit button icons based on status
  • Support for keyboard shortcuts (Enter to submit, Shift+Enter for new line)
  • Customizable min/max height for the textarea
  • Flexible toolbar with support for custom actions and tools
  • Built-in model selection dropdown
  • Built-in native speech recognition button (Web Speech API)
  • Optional provider for lifted state management
  • Form automatically resets on submit
  • Responsive design with mobile-friendly controls
  • Clean, modern styling with customizable themes
  • Form-based submission handling
  • Hidden file input sync for native form posts
  • Global document drop support (opt-in)

Examples


Cursor style

Preview

Code

11 Tab

openai logoGPT-4o

Props


<PromptInput />

Prop

Type

onSubmit?(message: PromptInputMessage, event: FormEvent) => void

accept?string

multiple?boolean

globalDrop?boolean

syncHiddenInput?boolean

maxFiles?number

maxFileSize?number

onError?(err: { code: "max_files" | "max_file_size" | "accept", message: string }) => void

...props?React.HTMLAttributes<HTMLFormElement>

<PromptInputTextarea />

Prop

Type

...props?React.ComponentProps<typeof Textarea>

<PromptInputFooter />

Prop

Type

...props?React.HTMLAttributes<HTMLDivElement>

<PromptInputTools />

Prop

Type

...props?React.HTMLAttributes<HTMLDivElement>

<PromptInputButton />

Prop

Type

...props?React.ComponentProps<typeof Button>

<PromptInputSubmit />

Prop

Type

status?ChatStatus

...props?React.ComponentProps<typeof Button>

<PromptInputSelect />

Prop

Type

...props?React.ComponentProps<typeof Select>

<PromptInputSelectTrigger />

Prop

Type

...props?React.ComponentProps<typeof SelectTrigger>

<PromptInputSelectContent />

Prop

Type

...props?React.ComponentProps<typeof SelectContent>

<PromptInputSelectItem />

Prop

Type

...props?React.ComponentProps<typeof SelectItem>

<PromptInputSelectValue />

Prop

Type

...props?React.ComponentProps<typeof SelectValue>

<PromptInputBody />

Prop

Type

...props?React.HTMLAttributes<HTMLDivElement>

<PromptInputAttachments />

Prop

Type

children?(attachment: FileUIPart & { id: string }) => React.ReactNode

...props?React.HTMLAttributes<HTMLDivElement>

<PromptInputAttachment />

Prop

Type

data?FileUIPart & { id: string }

...props?React.HTMLAttributes<HTMLDivElement>

<PromptInputActionMenu />

Prop

Type

...props?React.ComponentProps<typeof DropdownMenu>

<PromptInputActionMenuTrigger />

Prop

Type

...props?React.ComponentProps<typeof Button>

<PromptInputActionMenuContent />

Prop

Type

...props?React.ComponentProps<typeof DropdownMenuContent>

<PromptInputActionMenuItem />

Prop

Type

...props?React.ComponentProps<typeof DropdownMenuItem>

<PromptInputActionAddAttachments />

Prop

Type

label?string

...props?React.ComponentProps<typeof DropdownMenuItem>

<PromptInputProvider />

Prop

Type

initialInput?string

children?React.ReactNode

Optional global provider that lifts PromptInput state outside of PromptInput. When used, it allows you to access and control the input state from anywhere within the provider tree. If not used, PromptInput stays fully self-managed.

<PromptInputSpeechButton />

Prop

Type

textareaRef?RefObject<HTMLTextAreaElement | null>

onTranscriptionChange?(text: string) => void

...props?React.ComponentProps<typeof PromptInputButton>

Built-in button component that provides native speech recognition using the Web Speech API. The button will be disabled if speech recognition is not supported in the browser. Displays a microphone icon and pulses while actively listening.

Hooks


usePromptInputAttachments

Access and manage file attachments within a PromptInput context.

const attachments = usePromptInputAttachments();

// Available methods:
attachments.files // Array of current attachments
attachments.add(files) // Add new files
attachments.remove(id) // Remove an attachment by ID
attachments.clear() // Clear all attachments
attachments.openFileDialog() // Open file selection dialog

usePromptInputController

Access the full PromptInput controller from a PromptInputProvider. Only available when using the provider.

const controller = usePromptInputController();

// Available methods:
controller.textInput.value // Current text input value
controller.textInput.setInput(value) // Set text input value
controller.textInput.clear() // Clear text input
controller.attachments // Same as usePromptInputAttachments

useProviderAttachments

Access attachments context from a PromptInputProvider. Only available when using the provider.

const attachments = useProviderAttachments();

// Same interface as usePromptInputAttachments

<PromptInputHeader />

Prop

Type

...props?Omit<React.ComponentProps<typeof InputGroupAddon>, "align">

<PromptInputHoverCard />

Prop

Type

openDelay?number

closeDelay?number

...props?React.ComponentProps<typeof HoverCard>

<PromptInputHoverCardTrigger />

Prop

Type

...props?React.ComponentProps<typeof HoverCardTrigger>

<PromptInputHoverCardContent />

Prop

Type

align?"start" | "center" | "end"

...props?React.ComponentProps<typeof HoverCardContent>

<PromptInputTabsList />

Prop

Type

...props?React.HTMLAttributes<HTMLDivElement>

<PromptInputTab />

Prop

Type

...props?React.HTMLAttributes<HTMLDivElement>

<PromptInputTabLabel />

Prop

Type

...props?React.HTMLAttributes<HTMLHeadingElement>

<PromptInputTabBody />

Prop

Type

...props?React.HTMLAttributes<HTMLDivElement>

<PromptInputTabItem />

Prop

Type

...props?React.HTMLAttributes<HTMLDivElement>

<PromptInputCommand />

Prop

Type

...props?React.ComponentProps<typeof Command>

<PromptInputCommandInput />

Prop

Type

...props?React.ComponentProps<typeof CommandInput>

<PromptInputCommandList />

Prop

Type

...props?React.ComponentProps<typeof CommandList>

<PromptInputCommandEmpty />

Prop

Type

...props?React.ComponentProps<typeof CommandEmpty>

<PromptInputCommandGroup />

Prop

Type

...props?React.ComponentProps<typeof CommandGroup>

<PromptInputCommandItem />

Prop

Type

...props?React.ComponentProps<typeof CommandItem>

<PromptInputCommandSeparator />

Prop

Type

...props?React.ComponentProps<typeof CommandSeparator>

Plan

A collapsible plan component for displaying AI-generated execution plans with streaming support and shimmer animations.
Queue

A comprehensive queue component system for displaying message lists, todos, and collapsible task sections in AI applications.

On this page

Installation Usage with AI SDK Features Examples Cursor style Props <PromptInput /> <PromptInputTextarea /> <PromptInputFooter /> <PromptInputTools /> <PromptInputButton /> <PromptInputSubmit /> <PromptInputSelect /> <PromptInputSelectTrigger /> <PromptInputSelectContent /> <PromptInputSelectItem /> <PromptInputSelectValue /> <PromptInputBody /> <PromptInputAttachments /> <PromptInputAttachment /> <PromptInputActionMenu /> <PromptInputActionMenuTrigger /> <PromptInputActionMenuContent /> <PromptInputActionMenuItem /> <PromptInputActionAddAttachments /> <PromptInputProvider /> <PromptInputSpeechButton /> Hooks usePromptInputAttachments usePromptInputController useProviderAttachments <PromptInputHeader /> <PromptInputHoverCard /> <PromptInputHoverCardTrigger /> <PromptInputHoverCardContent /> <PromptInputTabsList /> <PromptInputTab /> <PromptInputTabLabel /> <PromptInputTabBody /> <PromptInputTabItem /> <PromptInputCommand /> <PromptInputCommandInput /> <PromptInputCommandList /> <PromptInputCommandEmpty /> <PromptInputCommandGroup /> <PromptInputCommandItem /> <PromptInputCommandSeparator />

GitHubEdit this page on GitHub Scroll to topCopy pageOpen in chat