File: prompt-input.md | Updated: 11/15/2025
Slash Forward
Docs Cookbook Providers Playground AI ElementsAI ElementsLeft sparkleRight sparkle AI GatewayGateway
Search...⌘KFeedback GitHub Vercel LogoSign in with Vercel
Chatbot
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
SearchGPT-4o
AI Elements
shadcn CLI
Manual
npx ai-elements@latest add prompt-input
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();
}
Preview
Code
11 Tab
GPT-4o
<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.
usePromptInputAttachmentsAccess 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
usePromptInputControllerAccess 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
useProviderAttachmentsAccess 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