File: message.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
A comprehensive suite of components for displaying chat messages, including message rendering, branching, actions, and markdown responses.
The Message component suite provides a complete set of tools for building chat interfaces. It includes components for displaying messages from users and AI assistants, managing multiple response branches, adding action buttons, and rendering markdown content.
Preview
Code
How do React hooks work and when should I use them?
React hooks are functions that let you "hook into" React state and lifecycle features from function components. Here's what you need to know:
Adds state to functional components:
jsx
Handles side effects (data fetching, subscriptions, DOM updates):
jsx
Would you like to explore more advanced hooks like useCallback or useMemo?
React hooks are special functions that let you use React features in function components. The most common ones are:
Here's a simple example:
jsx
Which specific hook would you like to learn more about?
Absolutely! React hooks are a powerful feature introduced in React 16.8. They solve several problems:
| Hook | Purpose | | --- | --- | | useState | Add state to components | | useEffect | Handle side effects | | useContext | Access context values | | useReducer | Complex state logic | | useCallback | Memoize functions | | useMemo | Memoize values |
The beauty of hooks is that they let you reuse stateful logic without changing your component hierarchy. Want to dive into a specific hook?
RetryLikeDislikeCopy
Important: After adding the component, you'll need to add the following to your globals.css file:
@source "../node_modules/streamdown/dist/index.js";
This is required for the MessageResponse component to work properly. Without this import, the Streamdown styles will not be applied to your project. See Streamdown's documentation for more details.
AI Elements
shadcn CLI
Manual
npx ai-elements@latest add message
Branching is an advanced use case you can implement to suit your needs. While the AI SDK does not provide built-in branching support, you have full flexibility to design and manage multiple response paths.
Build a simple chat UI where the user can copy or regenerate the most recent message.
Add the following component to your frontend:
app/page.tsx
'use client';
import { useState } from 'react';
import { MessageActions, MessageAction } from '@/components/ai-elements/message';
import { Message, MessageContent } from '@/components/ai-elements/message';
import {
Conversation,
ConversationContent,
ConversationScrollButton,
} from '@/components/ai-elements/conversation';
import {
Input,
PromptInputTextarea,
PromptInputSubmit,
} from '@/components/ai-elements/prompt-input';
import { MessageResponse } from '@/components/ai-elements/message';
import { RefreshCcwIcon, CopyIcon } from 'lucide-react';
import { useChat } from '@ai-sdk/react';
import { Fragment } from 'react';
const ActionsDemo = () => {
const [input, setInput] = useState('');
const { messages, sendMessage, status, regenerate } = useChat();
const handleSubmit = (e: React.FormEvent) => {
e.preventDefault();
if (input.trim()) {
sendMessage({ text: input });
setInput('');
}
};
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, messageIndex) => (
<Fragment key={message.id}>
{message.parts.map((part, i) => {
switch (part.type) {
case 'text':
const isLastMessage =
messageIndex === messages.length - 1;
return (
<Fragment key={`${message.id}-${i}`}>
<Message from={message.role}>
<MessageContent>
<MessageResponse>{part.text}</MessageResponse>
</MessageContent>
</Message>
{message.role === 'assistant' && isLastMessage && (
<MessageActions>
<MessageAction
onClick={() => regenerate()}
label="Retry"
>
<RefreshCcwIcon className="size-3" />
</MessageAction>
<MessageAction
onClick={() =>
navigator.clipboard.writeText(part.text)
}
label="Copy"
>
<CopyIcon className="size-3" />
</MessageAction>
</MessageActions>
)}
</Fragment>
);
default:
return null;
}
})}
</Fragment>
))}
</ConversationContent>
<ConversationScrollButton />
</Conversation>
<Input
onSubmit={handleSubmit}
className="mt-4 w-full max-w-2xl mx-auto relative"
>
<PromptInputTextarea
value={input}
placeholder="Say something..."
onChange={(e) => setInput(e.currentTarget.value)}
className="pr-12"
/>
<PromptInputSubmit
status={status === 'streaming' ? 'streaming' : 'ready'}
disabled={!input.trim()}
className="absolute bottom-1 right-1"
/>
</Input>
</div>
</div>
);
};
export default ActionsDemo;
<Message />Prop
Type
from?UIMessage["role"]
...props?React.HTMLAttributes<HTMLDivElement>
<MessageContent />Prop
Type
...props?React.HTMLAttributes<HTMLDivElement>
<MessageResponse />Prop
Type
children?string
parseIncompleteMarkdown?boolean
className?string
components?object
allowedImagePrefixes?string[]
allowedLinkPrefixes?string[]
defaultOrigin?string
rehypePlugins?array
remarkPlugins?array
...props?React.HTMLAttributes<HTMLDivElement>
<MessageActions />Prop
Type
...props?React.HTMLAttributes<HTMLDivElement>
<MessageAction />Prop
Type
tooltip?string
label?string
...props?React.ComponentProps<typeof Button>
<MessageBranch />Prop
Type
defaultBranch?number
onBranchChange?(branchIndex: number) => void
...props?React.HTMLAttributes<HTMLDivElement>
<MessageBranchContent />Prop
Type
...props?React.HTMLAttributes<HTMLDivElement>
<MessageBranchSelector />Prop
Type
from?UIMessage["role"]
...props?React.HTMLAttributes<HTMLDivElement>
<MessageBranchPrevious />Prop
Type
...props?React.ComponentProps<typeof Button>
<MessageBranchNext />Prop
Type
...props?React.ComponentProps<typeof Button>
<MessageBranchPage />Prop
Type
...props?React.HTMLAttributes<HTMLSpanElement>
<MessageAttachments />A container component for displaying file attachments in a message. Automatically positions attachments at the end of the message with proper spacing and alignment.
Prop
Type
children?ReactNode
...props?React.ComponentProps<"div">
Example:
<MessageAttachments className="mb-2">
{files.map((attachment) => (
<MessageAttachment data={attachment} key={attachment.url} />
))}
</MessageAttachments>
<MessageAttachment />Displays a single file attachment. Images are shown as thumbnails (96px × 96px) with rounded corners. Non-image files show a paperclip icon with the filename.
Prop
Type
data?FileUIPart
onRemove?() => void
...props?React.HTMLAttributes<HTMLDivElement>
Example:
<MessageAttachment
data={{
type: "file",
url: "https://example.com/image.jpg",
mediaType: "image/jpeg",
filename: "image.jpg"
}}
onRemove={() => console.log("Remove clicked")}
/>
Inline Citation
A hoverable citation component that displays source information and quotes inline with text, perfect for AI-generated content with references.
Model Selector
A searchable command palette for selecting AI models in your chat interface.
On this page
Installation
Features
Usage with AI SDK
Props
<Message />
<MessageContent />
<MessageResponse />
<MessageActions />
<MessageAction />
<MessageBranch />
<MessageBranchContent />
<MessageBranchSelector />
<MessageBranchPrevious />
<MessageBranchNext />
<MessageBranchPage />
<MessageAttachments />
<MessageAttachment />
GitHubEdit this page on GitHub Scroll to topCopy pageOpen in chat