AI Elements are a collection of React components specifically designed for building AI-powered applications. These components integrate seamlessly with the Vercel AI SDK and provide a consistent, accessible interface for AI interactions.
What are AI Elements?
AI Elements are pre-built React components that handle common AI application patterns:
- Chat interfaces with streaming responses
- Message handling with user and assistant roles
- Tool execution with real-time feedback
- File attachments and image handling
- Loading states and error handling
- Conversation management with auto-scrolling
Installation
AI Elements are included with shadcn/ui v4. To use them, you need to install the AI SDK:
pnpm add ai @ai-sdk/openai
Core Components
Message Components
Message
The base component for displaying individual messages in a conversation.
import {
Message,
MessageAvatar,
MessageContent,
} from "@/components/ai-elements/message"
export function ChatMessage({ message }) {
return (
<Message from={message.role}>
<MessageAvatar src={message.avatar} name={message.name} />
<MessageContent variant="contained">{message.content}</MessageContent>
</Message>
)
}
Props:
from
:"user" | "assistant"
- The role of the message sendervariant
:"contained" | "flat"
- Visual style variant
MessageContent
Container for message content with built-in styling for user and assistant messages.
<MessageContent variant="contained">
<p>Your message content here</p>
</MessageContent>
MessageAvatar
Avatar component for displaying user and assistant profile pictures.
<MessageAvatar src="/path/to/avatar.jpg" name="John Doe" />
Conversation Components
Conversation
The main container for chat conversations with auto-scrolling behavior.
import {
Conversation,
ConversationContent,
} from "@/components/ai-elements/conversation"
export function ChatInterface() {
return (
<Conversation>
<ConversationContent>{/* Your messages here */}</ConversationContent>
</Conversation>
)
}
ConversationEmptyState
Displays when there are no messages in the conversation.
import { ConversationEmptyState } from "@/components/ai-elements/conversation"
;<ConversationEmptyState
title="No messages yet"
description="Start a conversation to see messages here"
icon={<ChatIcon />}
/>
ConversationScrollButton
A button that appears when the user has scrolled up, allowing them to return to the bottom.
import { ConversationScrollButton } from "@/components/ai-elements/conversation"
;<ConversationScrollButton />
Input Components
PromptInput
A comprehensive input component for chat interfaces with file attachment support.
import {
PromptInput,
PromptInputAttachment,
PromptInputAttachments,
PromptInputBody,
PromptInputSubmit,
PromptInputTextarea,
PromptInputToolbar,
} from "@/components/ai-elements/prompt-input"
export function ChatInput({ onSubmit }) {
return (
<PromptInput onSubmit={onSubmit}>
<PromptInputBody>
<PromptInputAttachments>
{(attachment) => <PromptInputAttachment data={attachment} />}
</PromptInputAttachments>
<PromptInputTextarea placeholder="What would you like to know?" />
</PromptInputBody>
<PromptInputToolbar>
<PromptInputSubmit />
</PromptInputToolbar>
</PromptInput>
)
}
Features:
- File drag & drop support
- Image preview
- Auto-resizing textarea
- Keyboard shortcuts (Enter to send, Shift+Enter for new line)
- Paste file support
PromptInputSubmit
Submit button with loading states based on chat status.
<PromptInputSubmit status="streaming" />
Status options:
"submitted"
- Shows loading spinner"streaming"
- Shows stop icon"error"
- Shows error iconundefined
- Shows send icon
Response Components
Response
Component for displaying AI responses with streaming support.
import { Response } from "@/components/ai-elements/response"
export function AIResponse({ content }) {
return <Response>{content}</Response>
}
Utility Components
Loader
Animated loading spinner for AI processing states.
import { Loader } from "@/components/ai-elements/loader"
;<Loader size={16} />
Suggestions
Horizontal scrollable list of suggestion buttons.
import { Suggestion, Suggestions } from "@/components/ai-elements/suggestion"
export function SuggestionList({ suggestions, onSuggestionClick }) {
return (
<Suggestions>
{suggestions.map((suggestion) => (
<Suggestion
key={suggestion}
suggestion={suggestion}
onClick={onSuggestionClick}
/>
))}
</Suggestions>
)
}
Tool Components
Tool
Collapsible component for displaying tool execution details.
import {
Tool,
ToolContent,
ToolHeader,
ToolInput,
ToolOutput,
} from "@/components/ai-elements/tool"
export function ToolExecution({ tool }) {
return (
<Tool>
<ToolHeader title={tool.name} type={tool.type} state={tool.state} />
<ToolContent>
<ToolInput input={tool.input} />
<ToolOutput output={tool.output} errorText={tool.errorText} />
</ToolContent>
</Tool>
)
}
Tool States:
"input-streaming"
- Tool is receiving input"input-available"
- Tool is processing"output-available"
- Tool completed successfully"output-error"
- Tool encountered an error
Media Components
GeneratedImage
Component for displaying AI-generated images.
import { GeneratedImage } from "@/components/ai-elements/image"
;<GeneratedImage
base64={imageData.base64}
mediaType={imageData.mediaType}
alt="AI generated image"
/>
Action Components
Actions
Container for message action buttons (retry, copy, etc.).
import { Action, Actions } from "@/components/ai-elements/actions"
export function MessageActions() {
return (
<Actions>
<Action tooltip="Retry message" label="Retry">
<RetryIcon />
</Action>
<Action tooltip="Copy message" label="Copy">
<CopyIcon />
</Action>
</Actions>
)
}
Props:
tooltip
: Optional tooltip textlabel
: Accessibility labelvariant
: Button variantsize
: Button size
Context Components
Context
Displays AI model context usage and cost information.
import {
Context,
ContextContent,
ContextContentBody,
ContextContentFooter,
ContextContentHeader,
ContextInputUsage,
ContextOutputUsage,
ContextTrigger,
} from "@/components/ai-elements/context"
export function ContextUsage({ usage, modelId }) {
return (
<Context
usedTokens={usage.inputTokens + usage.outputTokens}
maxTokens={8000}
usage={usage}
modelId={modelId}
>
<ContextTrigger />
<ContextContent>
<ContextContentHeader />
<ContextContentBody>
<ContextInputUsage />
<ContextOutputUsage />
</ContextContentBody>
<ContextContentFooter />
</ContextContent>
</Context>
)
}
Features:
- Token usage visualization
- Cost estimation
- Progress indicators
- Hover card display
Artifact Components
Artifact
Container for AI-generated artifacts (tables, charts, etc.).
import {
Artifact,
ArtifactAction,
ArtifactActions,
ArtifactClose,
ArtifactContent,
ArtifactDescription,
ArtifactHeader,
ArtifactTitle,
} from "@/components/ai-elements/artifact"
export function ArtifactDisplay({ title, description, children }) {
return (
<Artifact>
<ArtifactHeader>
<div>
<ArtifactTitle>{title}</ArtifactTitle>
<ArtifactDescription>{description}</ArtifactDescription>
</div>
<ArtifactActions>
<ArtifactAction tooltip="Download" icon={DownloadIcon} />
<ArtifactAction tooltip="Share" icon={ShareIcon} />
<ArtifactClose />
</ArtifactActions>
</ArtifactHeader>
<ArtifactContent>{children}</ArtifactContent>
</Artifact>
)
}
Source Components
Sources
Displays source citations and references.
import {
Source,
Sources,
SourcesContent,
SourcesTrigger,
} from "@/components/ai-elements/sources"
export function SourceCitations({ sources }) {
return (
<Sources>
<SourcesTrigger count={sources.length} />
<SourcesContent>
{sources.map((source, index) => (
<Source key={index} href={source.url} title={source.title} />
))}
</SourcesContent>
</Sources>
)
}
Branch Components
Branch
Manages multiple conversation branches or alternative responses.
import {
Branch,
BranchMessages,
BranchNext,
BranchPage,
BranchPrevious,
BranchSelector,
} from "@/components/ai-elements/branch"
export function BranchingChat({ messages }) {
return (
<Branch defaultBranch={0}>
<BranchMessages>
{messages.map((branch, index) => (
<div key={index}>
{branch.map((message) => (
<Message key={message.id} from={message.role}>
<MessageContent>{message.content}</MessageContent>
</Message>
))}
</div>
))}
</BranchMessages>
<BranchSelector from="assistant">
<BranchPrevious />
<BranchPage />
<BranchNext />
</BranchSelector>
</Branch>
)
}
Features:
- Navigate between different conversation branches
- Automatic branch detection
- Keyboard navigation support
Chain of Thought Components
ChainOfThought
Displays AI reasoning process step by step.
import {
ChainOfThought,
ChainOfThoughtContent,
ChainOfThoughtHeader,
ChainOfThoughtImage,
ChainOfThoughtSearchResult,
ChainOfThoughtSearchResults,
ChainOfThoughtStep,
} from "@/components/ai-elements/chain-of-thought"
export function ReasoningDisplay({ steps }) {
return (
<ChainOfThought>
<ChainOfThoughtHeader>Analysis Process</ChainOfThoughtHeader>
<ChainOfThoughtContent>
{steps.map((step, index) => (
<ChainOfThoughtStep
key={index}
label={step.label}
description={step.description}
status={step.status}
icon={step.icon}
>
{step.content}
</ChainOfThoughtStep>
))}
<ChainOfThoughtSearchResults>
<ChainOfThoughtSearchResult>
Search Result 1
</ChainOfThoughtSearchResult>
<ChainOfThoughtSearchResult>
Search Result 2
</ChainOfThoughtSearchResult>
</ChainOfThoughtSearchResults>
<ChainOfThoughtImage caption="Analysis visualization">
<img src="/analysis-chart.png" alt="Analysis" />
</ChainOfThoughtImage>
</ChainOfThoughtContent>
</ChainOfThought>
)
}
Reasoning Components
Reasoning
Shows AI thinking process with auto-collapse behavior.
import {
Reasoning,
ReasoningContent,
ReasoningTrigger,
} from "@/components/ai-elements/reasoning"
export function AIReasoning({ isStreaming, reasoning }) {
return (
<Reasoning isStreaming={isStreaming} defaultOpen={true}>
<ReasoningTrigger />
<ReasoningContent>{reasoning}</ReasoningContent>
</Reasoning>
)
}
Features:
- Auto-opens during streaming
- Auto-closes after completion
- Duration tracking
- Collapsible interface
Complete Example
Here's a complete chat interface using AI Elements:
"use client"
import { useChat } from "ai/react"
import {
Conversation,
ConversationContent,
ConversationEmptyState,
ConversationScrollButton,
Loader,
Message,
MessageAvatar,
MessageContent,
PromptInput,
PromptInputBody,
PromptInputSubmit,
PromptInputTextarea,
PromptInputToolbar,
Response,
} from "@/components/ai-elements"
export function ChatInterface() {
const { messages, input, handleInputChange, handleSubmit, isLoading } =
useChat()
return (
<div className="flex h-screen flex-col">
<Conversation>
<ConversationContent>
{messages.length === 0 ? (
<ConversationEmptyState
title="Start a conversation"
description="Ask me anything!"
/>
) : (
messages.map((message) => (
<Message key={message.id} from={message.role}>
<MessageAvatar
src={
message.role === "user"
? "/user-avatar.jpg"
: "/ai-avatar.jpg"
}
name={message.role === "user" ? "You" : "AI"}
/>
<MessageContent>
<Response>{message.content}</Response>
</MessageContent>
</Message>
))
)}
{isLoading && (
<Message from="assistant">
<MessageAvatar src="/ai-avatar.jpg" name="AI" />
<MessageContent>
<Loader />
</MessageContent>
</Message>
)}
</ConversationContent>
<ConversationScrollButton />
</Conversation>
<PromptInput onSubmit={handleSubmit}>
<PromptInputBody>
<PromptInputTextarea
value={input}
onChange={handleInputChange}
placeholder="What would you like to know?"
/>
</PromptInputBody>
<PromptInputToolbar>
<PromptInputSubmit />
</PromptInputToolbar>
</PromptInput>
</div>
)
}
Styling and Theming
AI Elements inherit your shadcn/ui theme configuration. They use CSS variables for colors and can be customized through your globals.css
:
:root {
--background: 0 0% 100%;
--foreground: 222.2 84% 4.9%;
--primary: 222.2 47.4% 11.2%;
--primary-foreground: 210 40% 98%;
/* ... other variables */
}
Integration with AI SDK
AI Elements are designed to work seamlessly with the Vercel AI SDK. Here's how to integrate them:
import { useChat } from "ai/react"
import { Message, MessageContent } from "@/components/ai-elements/message"
export function ChatWithAI() {
const { messages, input, handleInputChange, handleSubmit } = useChat({
api: "/api/chat",
})
return (
<div>
{messages.map((message) => (
<Message key={message.id} from={message.role}>
<MessageContent>{message.content}</MessageContent>
</Message>
))}
<form onSubmit={handleSubmit}>
<input
value={input}
onChange={handleInputChange}
placeholder="Type your message..."
/>
<button type="submit">Send</button>
</form>
</div>
)
}
Best Practices
- Use semantic HTML: AI Elements use proper ARIA attributes for accessibility
- Handle loading states: Always show loading indicators during AI processing
- Provide feedback: Use tool components to show AI reasoning and actions
- Optimize for mobile: AI Elements are responsive by default
- Customize carefully: Modify components thoughtfully to maintain consistency
Accessibility
AI Elements are built with accessibility in mind:
- Proper ARIA labels and roles
- Keyboard navigation support
- Screen reader compatibility
- Focus management
- Color contrast compliance
Next Steps
On This Page
What are AI Elements?InstallationCore ComponentsMessage ComponentsMessageMessageContentMessageAvatarConversation ComponentsConversationConversationEmptyStateConversationScrollButtonInput ComponentsPromptInputPromptInputSubmitResponse ComponentsResponseUtility ComponentsLoaderSuggestionsTool ComponentsToolMedia ComponentsGeneratedImageAction ComponentsActionsContext ComponentsContextArtifact ComponentsArtifactSource ComponentsSourcesBranch ComponentsBranchChain of Thought ComponentsChainOfThoughtReasoning ComponentsReasoningComplete ExampleStyling and ThemingIntegration with AI SDKBest PracticesAccessibilityNext Steps