
Ai Elements
- 48 installs
- vercel-labs/vercel-skills
This is a copy of ai-elements by vercel - installs and ranking accrue to the original listing.
Scaffold new AI chat UI pieces for the ai-elements registry so your Next.js app matches shadcn/ui and Vercel AI SDK patterns without guessing folder structure.
About
AI Elements is a Vercel-maintained agent skill for solo builders extending the ai-elements component library—the shadcn/ui-based registry for AI-native UIs built on the Vercel AI SDK. Invoke it when you need a new chat-related component in packages/elements/src or when you ask the agent to add a component to ai-elements. The skill encodes composable patterns, registry layout, and install paths (CLI or shadcn) so generated code stays consistent with existing elements like conversations and messages. It fits indie SaaS and agent-product teams already on Next.js 18+ who want faster iteration on streaming chat UX without re-reading the full docs each time. Prerequisites are a Next.js project with AI SDK and shadcn/ui; the workflow emphasizes alignment with Vercel AI Gateway for keys and routing. Use during Build when the interface is the bottleneck, not during idea validation or post-launch growth tooling.
- Guides adding components under packages/elements/src with ai-elements + shadcn/ui conventions
- Assumes Next.js, AI SDK, and shadcn/ui (install commands can bootstrap shadcn if missing)
- Covers conversations, messages, and related AI-native UI patterns from the npm ai-elements package
- Recommends Vercel AI Gateway and AI_GATEWAY_API_KEY for production API routing
- Supports dedicated ai-elements CLI or standard shadcn/ui registry workflow
Ai Elements by the numbers
- 48 all-time installs (skills.sh)
- Security screen: CRITICAL risk (skills.sh audit)
- Data as of Jul 7, 2026 (Skillselion catalog sync)
npx skills add https://github.com/vercel-labs/vercel-skills --skill ai-elementsAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 48 |
|---|---|
| Security audit | 2 / 3 scanners passed |
| Repository | vercel-labs/vercel-skills ↗ |
What it does
Scaffold new AI chat UI pieces for the ai-elements registry so your Next.js app matches shadcn/ui and Vercel AI SDK patterns without guessing folder structure.
Files
AI Elements
AI Elements is a component library and custom registry built on top of shadcn/ui to help you build AI-native applications faster. It provides pre-built components like conversations, messages and more.
Installing AI Elements is straightforward and can be done in a couple of ways. You can use the dedicated CLI command for the fastest setup, or integrate via the standard shadcn/ui CLI if you've already adopted shadcn's workflow.
Quick Start
Here are some basic examples of what you can achieve using components from AI Elements.
Prerequisites
Before installing AI Elements, make sure your environment meets the following requirements:
- Node.js, version 18 or later
- A Next.js project with the AI SDK installed.
- shadcn/ui installed in your project. If you don't have it installed, running any install command will automatically install it for you.
- We also highly recommend using the AI Gateway and adding
AI_GATEWAY_API_KEYto yourenv.localso you don't have to use an API key from every provider. AI Gateway also gives $5 in usage per month so you can experiment with models. You can obtain an API key here.
Installing Components
You can install AI Elements components using either the AI Elements CLI or the shadcn/ui CLI. Both achieve the same result: adding the selected component’s code and any needed dependencies to your project.
The CLI will download the component’s code and integrate it into your project’s directory (usually under your components folder). By default, AI Elements components are added to the @/components/ai-elements/ directory (or whatever folder you’ve configured in your shadcn components settings).
After running the command, you should see a confirmation in your terminal that the files were added. You can then proceed to use the component in your code.
Usage
Once an AI Elements component is installed, you can import it and use it in your application like any other React component. The components are added as part of your codebase (not hidden in a library), so the usage feels very natural.
Example
After installing AI Elements components, you can use them in your application like any other React component. For example:
```tsx title="conversation.tsx" "use client";
import { Message, MessageContent, MessageResponse, } from "@/components/ai-elements/message"; import { useChat } from "@ai-sdk/react";
const Example = () => { const { messages } = useChat();
return ( <> {messages.map(({ role, parts }, index) => ( <Message from={role} key={index}> <MessageContent> {parts.map((part, i) => { switch (part.type) { case "text": return ( <MessageResponse key={${role}-${i}}> {part.text} </MessageResponse> ); } })} </MessageContent> </Message> ))} </> ); };
export default Example;
In the example above, we import the `Message` component from our AI Elements directory and include it in our JSX. Then, we compose the component with the `MessageContent` and `MessageResponse` subcomponents. You can style or configure the component just as you would if you wrote it yourself – since the code lives in your project, you can even open the component file to see how it works or make custom modifications.
## Extensibility
All AI Elements components take as many primitive attributes as possible. For example, the `Message` component extends `HTMLAttributes<HTMLDivElement>`, so you can pass any props that a `div` supports. This makes it easy to extend the component with your own styles or functionality.
## Customization
After installation, no additional setup is needed. The component’s styles (Tailwind CSS classes) and scripts are already integrated. You can start interacting with the component in your app immediately.
For example, if you'd like to remove the rounding on `Message`, you can go to `components/ai-elements/message.tsx` and remove `rounded-lg` as follows:
export const MessageContent = ({ children, className, ...props }: MessageContentProps) => ( <div className={cn( "flex flex-col gap-2 text-sm text-foreground", "group-[.is-user]:bg-primary group-[.is-user]:text-primary-foreground group-[.is-user]:px-4 group-[.is-user]:py-3", className )} {...props} > <div className="is-user:dark">{children}</div> </div> );
## Troubleshooting
## Why are my components not styled?
Make sure your project is configured correctly for shadcn/ui in Tailwind 4 - this means having a `globals.css` file that imports Tailwind and includes the shadcn/ui base styles.
## I ran the AI Elements CLI but nothing was added to my project
Double-check that:
- Your current working directory is the root of your project (where `package.json` lives).
- Your components.json file (if using shadcn-style config) is set up correctly.
- You’re using the latest version of the AI Elements CLI:
npx ai-elements@latest
If all else fails, feel free to open an [issue on GitHub](https://github.com/vercel/ai-elements/issues).
## Theme switching doesn’t work — my app stays in light mode
Ensure your app is using the same data-theme system that shadcn/ui and AI Elements expect. The default implementation toggles a data-theme attribute on the `<html>` element. Make sure your tailwind.config.js is using class or data- selectors accordingly:
## The component imports fail with “module not found”
Check the file exists. If it does, make sure your `tsconfig.json` has a proper paths alias for `@/` i.e.
{ "compilerOptions": { "baseUrl": ".", "paths": { "@/": ["./"] } } }
## My AI coding assistant can't access AI Elements components
1. Verify your config file syntax is valid JSON.
2. Check that the file path is correct for your AI tool.
3. Restart your coding assistant after making changes.
4. Ensure you have a stable internet connection.
## Still stuck?
If none of these answers help, open an [issue on GitHub](https://github.com/vercel/ai-elements/issues) and someone will be happy to assist.
## Available Components
See the `references/` folder for detailed documentation on each component.
Agent
A composable component for displaying AI agent configuration with model, instructions, tools, and output schema.
The Agent component displays an interface for showing AI agent configuration details. It's designed to represent a configured agent from the AI SDK, showing the agent's model, system instructions, available tools (with expandable input schemas), and output schema.
See scripts/agent.tsx for this example.
Installation
npx ai-elements@latest add agentUsage with AI SDK
Display an agent's configuration alongside your chat interface. Tools are displayed in an accordion where clicking the description expands to show the input schema.
```tsx title="app/page.tsx" "use client";
import { tool } from "ai"; import { z } from "zod"; import { Agent, AgentContent, AgentHeader, AgentInstructions, AgentOutput, AgentTool, AgentTools, } from "@/components/ai-elements/agent";
const webSearch = tool({ description: "Search the web for information", inputSchema: z.object({ query: z.string().describe("The search query"), }), });
const readUrl = tool({ description: "Read and parse content from a URL", inputSchema: z.object({ url: z.string().url().describe("The URL to read"), }), });
const outputSchema = z.object({ sentiment: z.enum(['positive', 'negative', 'neutral']), score: z.number(), summary: z.string(), });
export default function Page() { return ( <Agent> <AgentHeader name="Sentiment Analyzer" model="anthropic/claude-sonnet-4-5" /> <AgentContent> <AgentInstructions> Analyze the sentiment of the provided text and return a structured analysis with sentiment classification, confidence score, and summary. </AgentInstructions> <AgentTools> <AgentTool tool={webSearch} value="web_search" /> <AgentTool tool={readUrl} value="read_url" /> </AgentTools> <AgentOutput schema={outputSchema} /> </AgentContent> </Agent> ); }
## Features
- Model badge in header
- Instructions rendered as markdown
- Tools displayed as accordion items with expandable input schemas
- Output schema display with syntax highlighting
- Composable structure for flexible layouts
- Works with AI SDK `Tool` type
## Props
### `<Agent />`
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| `...props` | `React.ComponentProps<` | - | Any props are spread to the root div. |
### `<AgentHeader />`
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| `name` | `string` | Required | The name of the agent. |
| `model` | `string` | - | The model identifier (e.g. |
| `...props` | `React.ComponentProps<` | - | Any other props are spread to the container div. |
### `<AgentContent />`
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| `...props` | `React.ComponentProps<` | - | Any other props are spread to the container div. |
### `<AgentInstructions />`
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| `children` | `string` | Required | The instruction text. |
| `...props` | `React.ComponentProps<` | - | Any other props are spread to the container div. |
### `<AgentTools />`
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| `...props` | `React.ComponentProps<typeof Accordion>` | - | Any other props are spread to the Accordion component. |
### `<AgentTool />`
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| `tool` | `Tool` | Required | The tool object from the AI SDK containing description and inputSchema. |
| `value` | `string` | Required | Unique identifier for the accordion item. |
| `...props` | `React.ComponentProps<typeof AccordionItem>` | - | Any other props are spread to the AccordionItem component. |
### `<AgentOutput />`
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| `schema` | `string` | Required | The output schema as a string (displayed with syntax highlighting). |
| `...props` | `React.ComponentProps<` | - | Any other props are spread to the container div. |
Artifact
A container component for displaying generated content like code, documents, or other outputs with built-in actions.
The Artifact component provides a structured container for displaying generated content like code, documents, or other outputs with built-in header actions.
See scripts/artifact.tsx for this example.
Installation
npx ai-elements@latest add artifactFeatures
- Structured container with header and content areas
- Built-in header with title and description support
- Flexible action buttons with tooltips
- Customizable styling for all subcomponents
- Support for close buttons and action groups
- Clean, modern design with border and shadow
- Responsive layout that adapts to content
- TypeScript support with proper type definitions
- Composable architecture for maximum flexibility
Examples
With Code Display
See scripts/artifact.tsx for this example.
Props
<Artifact />
| Prop | Type | Default | Description |
|---|---|---|---|
...props | React.HTMLAttributes<HTMLDivElement> | - | Any other props are spread to the underlying div element. |
<ArtifactHeader />
| Prop | Type | Default | Description |
|---|---|---|---|
...props | React.HTMLAttributes<HTMLDivElement> | - | Any other props are spread to the underlying div element. |
<ArtifactTitle />
| Prop | Type | Default | Description |
|---|---|---|---|
...props | React.HTMLAttributes<HTMLParagraphElement> | - | Any other props are spread to the underlying paragraph element. |
<ArtifactDescription />
| Prop | Type | Default | Description |
|---|---|---|---|
...props | React.HTMLAttributes<HTMLParagraphElement> | - | Any other props are spread to the underlying paragraph element. |
<ArtifactActions />
| Prop | Type | Default | Description |
|---|---|---|---|
...props | React.HTMLAttributes<HTMLDivElement> | - | Any other props are spread to the underlying div element. |
<ArtifactAction />
| Prop | Type | Default | Description |
|---|---|---|---|
tooltip | string | - | Tooltip text to display on hover. |
label | string | - | Screen reader label for the action button. |
icon | LucideIcon | - | Lucide icon component to display in the button. |
...props | React.ComponentProps<typeof Button> | - | Any other props are spread to the underlying shadcn/ui Button component. |
<ArtifactClose />
| Prop | Type | Default | Description |
|---|---|---|---|
...props | React.ComponentProps<typeof Button> | - | Any other props are spread to the underlying shadcn/ui Button component. |
<ArtifactContent />
| Prop | Type | Default | Description |
|---|---|---|---|
...props | React.HTMLAttributes<HTMLDivElement> | - | Any other props are spread to the underlying div element. |
Attachments
A flexible, composable attachment component for displaying files, images, videos, audio, and source documents.
The Attachment component provides a unified way to display file attachments and source documents with multiple layout variants.
See scripts/attachments.tsx for this example.
Installation
npx ai-elements@latest add attachmentsUsage with AI SDK
Display user-uploaded files in chat messages or input areas.
```tsx title="app/page.tsx" "use client";
import { Attachments, Attachment, AttachmentPreview, AttachmentInfo, AttachmentRemove, } from "@/components/ai-elements/attachments"; import type { FileUIPart } from "ai";
interface MessageProps { attachments: (FileUIPart & { id: string })[]; onRemove?: (id: string) => void; }
const MessageAttachments = ({ attachments, onRemove }: MessageProps) => ( <Attachments variant="grid"> {attachments.map((file) => ( <Attachment key={file.id} data={file} onRemove={onRemove ? () => onRemove(file.id) : undefined} > <AttachmentPreview /> <AttachmentRemove /> </Attachment> ))} </Attachments> );
export default MessageAttachments;
## Features
- Three display variants: grid (thumbnails), inline (badges), and list (rows)
- Supports both FileUIPart and SourceDocumentUIPart from the AI SDK
- Automatic media type detection (image, video, audio, document, source)
- Hover card support for inline previews
- Remove button with customizable callback
- Composable architecture for maximum flexibility
- Accessible with proper ARIA labels
- TypeScript support with exported utility functions
## Examples
### Grid Variant
Best for displaying attachments in messages with visual thumbnails.
See `scripts/attachments.tsx` for this example.
### Inline Variant
Best for compact badge-style display in input areas with hover previews.
See `scripts/attachments-inline.tsx` for this example.
### List Variant
Best for file lists with full metadata display.
See `scripts/attachments-list.tsx` for this example.
## Props
### `<Attachments />`
Container component that sets the layout variant.
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| `variant` | `unknown` | - | The display layout variant. |
| `...props` | `React.HTMLAttributes<HTMLDivElement>` | - | Spread to the underlying div element. |
### `<Attachment />`
Individual attachment item wrapper.
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| `data` | `unknown` | - | The attachment data (FileUIPart or SourceDocumentUIPart with id). |
| `onRemove` | `() => void` | - | Callback fired when the remove button is clicked. |
| `...props` | `React.HTMLAttributes<HTMLDivElement>` | - | Spread to the underlying div element. |
### `<AttachmentPreview />`
Displays the media preview (image, video, or icon).
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| `fallbackIcon` | `React.ReactNode` | - | Custom icon to display when no preview is available. |
| `...props` | `React.HTMLAttributes<HTMLDivElement>` | - | Spread to the underlying div element. |
### `<AttachmentInfo />`
Displays the filename and optional media type.
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| `showMediaType` | `boolean` | `false` | Whether to show the media type below the filename. |
| `...props` | `React.HTMLAttributes<HTMLDivElement>` | - | Spread to the underlying div element. |
### `<AttachmentRemove />`
Remove button that appears on hover.
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| `label` | `string` | - | Screen reader label for the button. |
| `...props` | `React.ComponentProps<typeof Button>` | - | Spread to the underlying Button component. |
### `<AttachmentHoverCard />`
Wrapper for hover preview functionality.
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| `openDelay` | `number` | `0` | Delay in ms before opening the hover card. |
| `closeDelay` | `number` | `0` | Delay in ms before closing the hover card. |
| `...props` | `React.ComponentProps<typeof HoverCard>` | - | Spread to the underlying HoverCard component. |
### `<AttachmentHoverCardTrigger />`
Trigger element for the hover card.
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| `...props` | `React.ComponentProps<typeof HoverCardTrigger>` | - | Spread to the underlying HoverCardTrigger component. |
### `<AttachmentHoverCardContent />`
Content displayed in the hover card.
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| `align` | `unknown` | - | Alignment of the hover card content. |
| `...props` | `React.ComponentProps<typeof HoverCardContent>` | - | Spread to the underlying HoverCardContent component. |
### `<AttachmentEmpty />`
Empty state component when no attachments are present.
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| `...props` | `React.HTMLAttributes<HTMLDivElement>` | - | Spread to the underlying div element. |
## Utility Functions
### `getMediaCategory(data)`
Returns the media category for an attachment.
import { getMediaCategory } from "@/components/ai-elements/attachments";
const category = getMediaCategory(attachment); // Returns: "image" | "video" | "audio" | "document" | "source" | "unknown"
### `getAttachmentLabel(data)`
Returns the display label for an attachment.
import { getAttachmentLabel } from "@/components/ai-elements/attachments";
const label = getAttachmentLabel(attachment); // Returns filename or fallback like "Image" or "Attachment"
Audio Player
A composable audio player component built on media-chrome, with shadcn styling and flexible controls.
The AudioPlayer component provides a flexible and customizable audio playback interface built on top of media-chrome. It features a composable architecture that allows you to build audio experiences with custom controls, metadata display, and seamless integration with AI-generated audio content.
See scripts/audio-player.tsx for this example.
Installation
npx ai-elements@latest add audio-playerFeatures
- Built on media-chrome for reliable audio playback
- Fully composable architecture with granular control components
- ButtonGroup integration for cohesive control layout
- Individual control components (play, seek, volume, etc.)
- Flexible layout with customizable control bars
- CSS custom properties for deep theming
- Shadcn/ui Button component styling
- Responsive design that works across devices
- Full TypeScript support with proper types for all components
Variants
AI SDK Speech Result
The AudioPlayer component can be used to play audio from an AI SDK Speech Result.
See scripts/audio-player.tsx for this example.
Remote Audio
The AudioPlayer component can be used to play remote audio files.
See scripts/audio-player-remote.tsx for this example.
Props
<AudioPlayer />
Root MediaController component. Accepts all MediaController props except audio (which is set to true by default).
| Prop | Type | Default | Description |
|---|---|---|---|
style | CSSProperties | - | Custom CSS properties can be passed to override media-chrome theming variables. |
...props | Omit<React.ComponentProps<typeof MediaController>, | - | Any other props are spread to the MediaController component. |
<AudioPlayerElement />
The audio element that contains the media source. Accepts either a remote URL or AI SDK Speech Result data.
| Prop | Type | Default | Description |
|---|---|---|---|
src | string | - | The URL of the audio file to play (for remote audio). |
data | SpeechResult[ | - | AI SDK Speech Result audio data with base64 encoding (for AI-generated audio). |
...props | Omit<React.ComponentProps< | - | Any other props are spread to the audio element (excluding src when using data). |
<AudioPlayerControlBar />
Container for control buttons, wraps children in a ButtonGroup.
| Prop | Type | Default | Description |
|---|---|---|---|
...props | React.ComponentProps<typeof MediaControlBar> | - | Any other props are spread to the MediaControlBar component. |
<AudioPlayerPlayButton />
Play/pause button wrapped in a shadcn Button component.
| Prop | Type | Default | Description |
|---|---|---|---|
...props | React.ComponentProps<typeof MediaPlayButton> | - | Any other props are spread to the MediaPlayButton component. |
<AudioPlayerSeekBackwardButton />
Seek backward button wrapped in a shadcn Button component.
| Prop | Type | Default | Description |
|---|---|---|---|
seekOffset | number | 10 | The number of seconds to seek backward. |
...props | React.ComponentProps<typeof MediaSeekBackwardButton> | - | Any other props are spread to the MediaSeekBackwardButton component. |
<AudioPlayerSeekForwardButton />
Seek forward button wrapped in a shadcn Button component.
| Prop | Type | Default | Description |
|---|---|---|---|
seekOffset | number | 10 | The number of seconds to seek forward. |
...props | React.ComponentProps<typeof MediaSeekForwardButton> | - | Any other props are spread to the MediaSeekForwardButton component. |
<AudioPlayerTimeDisplay />
Displays the current playback time, wrapped in ButtonGroupText.
| Prop | Type | Default | Description |
|---|---|---|---|
...props | React.ComponentProps<typeof MediaTimeDisplay> | - | Any other props are spread to the MediaTimeDisplay component. |
<AudioPlayerTimeRange />
Seek slider for controlling playback position, wrapped in ButtonGroupText.
| Prop | Type | Default | Description |
|---|---|---|---|
...props | React.ComponentProps<typeof MediaTimeRange> | - | Any other props are spread to the MediaTimeRange component. |
<AudioPlayerDurationDisplay />
Displays the total duration of the audio, wrapped in ButtonGroupText.
| Prop | Type | Default | Description |
|---|---|---|---|
...props | React.ComponentProps<typeof MediaDurationDisplay> | - | Any other props are spread to the MediaDurationDisplay component. |
<AudioPlayerMuteButton />
Mute/unmute button, wrapped in ButtonGroupText.
| Prop | Type | Default | Description |
|---|---|---|---|
...props | React.ComponentProps<typeof MediaMuteButton> | - | Any other props are spread to the MediaMuteButton component. |
<AudioPlayerVolumeRange />
Volume slider control, wrapped in ButtonGroupText.
| Prop | Type | Default | Description |
|---|---|---|---|
...props | React.ComponentProps<typeof MediaVolumeRange> | - | Any other props are spread to the MediaVolumeRange component. |
Canvas
A React Flow-based canvas component for building interactive node-based interfaces.
The Canvas component provides a React Flow-based canvas for building interactive node-based interfaces. It comes pre-configured with sensible defaults for AI applications, including panning, zooming, and selection behaviors.
Installation
npx ai-elements@latest add canvasFeatures
- Pre-configured React Flow canvas with AI-optimized defaults
- Pan on scroll enabled for intuitive navigation
- Selection on drag for multi-node operations
- Customizable background color using CSS variables
- Delete key support (Backspace and Delete keys)
- Auto-fit view to show all nodes
- Disabled double-click zoom for better UX
- Disabled pan on drag to prevent accidental canvas movement
- Fully compatible with React Flow props and API
Props
<Canvas />
| Prop | Type | Default | Description |
|---|---|---|---|
children | ReactNode | - | Child components like Background, Controls, or MiniMap. |
...props | ReactFlowProps | - | Any other React Flow props like nodes, edges, nodeTypes, edgeTypes, onNodesChange, etc. |
Chain of Thought
A collapsible component that visualizes AI reasoning steps with support for search results, images, and step-by-step progress indicators.
The ChainOfThought component provides a visual representation of an AI's reasoning process, showing step-by-step thinking with support for search results, images, and progress indicators. It helps users understand how AI arrives at conclusions.
See scripts/chain-of-thought.tsx for this example.
Installation
npx ai-elements@latest add chain-of-thoughtFeatures
- Collapsible interface with smooth animations powered by Radix UI
- Step-by-step visualization of AI reasoning process
- Support for different step statuses (complete, active, pending)
- Built-in search results display with badge styling
- Image support with captions for visual content
- Custom icons for different step types
- Context-aware components using React Context API
- Fully typed with TypeScript
- Accessible with keyboard navigation support
- Responsive design that adapts to different screen sizes
- Smooth fade and slide animations for content transitions
- Composable architecture for flexible customization
Props
<ChainOfThought />
| Prop | Type | Default | Description |
|---|---|---|---|
open | boolean | - | Controlled open state of the collapsible. |
defaultOpen | boolean | false | Default open state when uncontrolled. |
onOpenChange | (open: boolean) => void | - | Callback when the open state changes. |
...props | React.ComponentProps< | - | Any other props are spread to the root div element. |
<ChainOfThoughtHeader />
| Prop | Type | Default | Description |
|---|---|---|---|
children | React.ReactNode | - | Custom header text. |
...props | React.ComponentProps<typeof CollapsibleTrigger> | - | Any other props are spread to the CollapsibleTrigger component. |
<ChainOfThoughtStep />
| Prop | Type | Default | Description |
|---|---|---|---|
icon | LucideIcon | DotIcon | Icon to display for the step. |
label | string | - | The main text label for the step. |
description | string | - | Optional description text shown below the label. |
status | unknown | - | Visual status of the step. |
...props | React.ComponentProps< | - | Any other props are spread to the root div element. |
<ChainOfThoughtSearchResults />
| Prop | Type | Default | Description |
|---|---|---|---|
...props | React.ComponentProps< | - | Any props are spread to the container div element. |
<ChainOfThoughtSearchResult />
| Prop | Type | Default | Description |
|---|---|---|---|
...props | React.ComponentProps<typeof Badge> | - | Any props are spread to the Badge component. |
<ChainOfThoughtContent />
| Prop | Type | Default | Description |
|---|---|---|---|
...props | React.ComponentProps<typeof CollapsibleContent> | - | Any props are spread to the CollapsibleContent component. |
<ChainOfThoughtImage />
| Prop | Type | Default | Description |
|---|---|---|---|
caption | string | - | Optional caption text displayed below the image. |
...props | React.ComponentProps< | - | Any other props are spread to the container div element. |
Checkpoint
A simple component for marking conversation history points and restoring the chat to a previous state.
The Checkpoint component provides a way to mark specific points in a conversation history and restore the chat to that state. Inspired by VSCode's Copilot checkpoint feature, it allows users to revert to an earlier conversation state while maintaining a clear visual separation between different conversation segments.
See scripts/checkpoint.tsx for this example.
Installation
npx ai-elements@latest add checkpointFeatures
- Simple flex layout with icon, trigger, and separator
- Visual separator line for clear conversation breaks
- Clickable restore button for reverting to checkpoint
- Customizable icon (defaults to BookmarkIcon)
- Keyboard accessible with proper ARIA labels
- Responsive design that adapts to different screen sizes
- Seamless light/dark theme integration
Usage with AI SDK
Build a chat interface with conversation checkpoints that allow users to restore to previous states.
Add the following component to your frontend:
```tsx title="app/page.tsx" "use client";
import { useState, Fragment } from "react"; import { useChat } from "@ai-sdk/react"; import { Checkpoint, CheckpointIcon, CheckpointTrigger, } from "@/components/ai-elements/checkpoint"; import { Message, MessageContent, MessageResponse, } from "@/components/ai-elements/message"; import { Conversation, ConversationContent, } from "@/components/ai-elements/conversation";
type CheckpointType = { id: string; messageIndex: number; timestamp: Date; messageCount: number; };
const CheckpointDemo = () => { const { messages, setMessages } = useChat(); const [checkpoints, setCheckpoints] = useState<CheckpointType[]>([]);
const createCheckpoint = (messageIndex: number) => { const checkpoint: CheckpointType = { id: nanoid(), messageIndex, timestamp: new Date(), messageCount: messageIndex + 1, }; setCheckpoints([...checkpoints, checkpoint]); };
const restoreToCheckpoint = (messageIndex: number) => { // Restore messages to checkpoint state setMessages(messages.slice(0, messageIndex + 1)); // Remove checkpoints after this point setCheckpoints(checkpoints.filter((cp) => cp.messageIndex <= messageIndex)); };
return ( <div className="max-w-4xl mx-auto p-6 relative size-full rounded-lg border h-[600px]"> <Conversation> <ConversationContent> {messages.map((message, index) => { const checkpoint = checkpoints.find( (cp) => cp.messageIndex === index );
return ( <Fragment key={message.id}> <Message from={message.role}> <MessageContent> <MessageResponse>{message.content}</MessageResponse> </MessageContent> </Message> {checkpoint && ( <Checkpoint> <CheckpointIcon /> <CheckpointTrigger onClick={() => restoreToCheckpoint(checkpoint.messageIndex) } > Restore checkpoint </CheckpointTrigger> </Checkpoint> )} </Fragment> ); })} </ConversationContent> </Conversation> </div> ); };
export default CheckpointDemo;
## Use Cases
### Manual Checkpoints
Allow users to manually create checkpoints at important conversation points:
<Button onClick={() => createCheckpoint(messages.length - 1)}> Create Checkpoint </Button>
### Automatic Checkpoints
Create checkpoints automatically after significant conversation milestones:
useEffect(() => { // Create checkpoint every 5 messages if (messages.length > 0 && messages.length % 5 === 0) { createCheckpoint(messages.length - 1); } }, [messages.length]);
### Branching Conversations
Use checkpoints to enable conversation branching where users can explore different conversation paths:
const restoreAndBranch = (messageIndex: number) => { // Save current branch const currentBranch = messages.slice(messageIndex + 1); saveBranch(currentBranch);
// Restore to checkpoint restoreToCheckpoint(messageIndex); };
## Props
### `<Checkpoint />`
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| `children` | `React.ReactNode` | - | The checkpoint icon and trigger components. Automatically includes a Separator at the end. |
| `...props` | `React.HTMLAttributes<HTMLDivElement>` | - | Any other props are spread to the root div. |
### `<CheckpointIcon />`
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| `children` | `React.ReactNode` | - | Custom icon content. If not provided, defaults to a BookmarkIcon from lucide-react. |
| `...props` | `LucideProps` | - | Any other props are spread to the BookmarkIcon component. |
### `<CheckpointTrigger />`
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| `children` | `React.ReactNode` | - | The text or content to display in the trigger button. |
| `variant` | `string` | - | The button variant style. |
| `size` | `string` | - | The button size. |
| `...props` | `React.ComponentProps<typeof Button>` | - | Any other props are spread to the underlying shadcn/ui Button component. |
Code Block
Provides syntax highlighting, line numbers, and copy to clipboard functionality for code blocks.
The CodeBlock component provides syntax highlighting, line numbers, and copy to clipboard functionality for code blocks. It's fully composable, allowing you to customize the header, actions, and content.
See scripts/code-block.tsx for this example.
Installation
npx ai-elements@latest add code-blockUsage
The CodeBlock is fully composable. Here's a basic example:
import {
CodeBlock,
CodeBlockActions,
CodeBlockCopyButton,
CodeBlockFilename,
CodeBlockHeader,
CodeBlockTitle,
} from "@/components/ai-elements/code-block";
import { FileIcon } from "lucide-react";
export const Example = () => (
<CodeBlock code={code} language="typescript">
<CodeBlockHeader>
<CodeBlockTitle>
<FileIcon size={14} />
<CodeBlockFilename>example.ts</CodeBlockFilename>
</CodeBlockTitle>
<CodeBlockActions>
<CodeBlockCopyButton />
</CodeBlockActions>
</CodeBlockHeader>
</CodeBlock>
);Features
- Syntax highlighting with Shiki
- Line numbers (optional)
- Copy to clipboard functionality
- Automatic light/dark theme switching via CSS variables
- Language selector for multi-language examples
- Fully composable architecture
- Accessible design
Examples
Dark Mode
To use the CodeBlock component in dark mode, wrap it in a div with the dark class.
See scripts/code-block-dark.tsx for this example.
Language Selector
Add a language selector to switch between different code implementations:
See scripts/code-block.tsx for this example.
Props
<CodeBlock />
| Prop | Type | Default | Description |
|---|---|---|---|
code | string | - | The code content to display. |
language | BundledLanguage | - | The programming language for syntax highlighting. |
showLineNumbers | boolean | false | Whether to show line numbers. |
children | React.ReactNode | - | Child elements like CodeBlockHeader. |
className | string | - | Additional CSS classes. |
<CodeBlockHeader />
Container for the header row. Uses flexbox with justify-between.
| Prop | Type | Default | Description |
|---|---|---|---|
children | React.ReactNode | - | Header content (CodeBlockTitle, CodeBlockActions, etc.). |
className | string | - | Additional CSS classes. |
<CodeBlockTitle />
Left-aligned container for icon and filename. Uses flexbox with gap-2.
| Prop | Type | Default | Description |
|---|---|---|---|
children | React.ReactNode | - | Title content (icon, CodeBlockFilename, etc.). |
className | string | - | Additional CSS classes. |
<CodeBlockFilename />
Displays the filename in monospace font.
| Prop | Type | Default | Description |
|---|---|---|---|
children | React.ReactNode | - | The filename to display. |
className | string | - | Additional CSS classes. |
<CodeBlockActions />
Right-aligned container for action buttons. Uses flexbox with gap-2.
| Prop | Type | Default | Description |
|---|---|---|---|
children | React.ReactNode | - | Action buttons (CodeBlockCopyButton, CodeBlockLanguageSelector, etc.). |
className | string | - | Additional CSS classes. |
<CodeBlockCopyButton />
| Prop | Type | Default | Description |
|---|---|---|---|
onCopy | () => void | - | Callback fired after a successful copy. |
onError | (error: Error) => void | - | Callback fired if copying fails. |
timeout | number | 2000 | How long to show the copied state (ms). |
children | React.ReactNode | - | Custom content for the button. Defaults to copy/check icons. |
className | string | - | Additional CSS classes. |
<CodeBlockLanguageSelector />
Wrapper for the language selector. Extends shadcn/ui Select.
| Prop | Type | Default | Description |
|---|---|---|---|
value | string | - | The currently selected language. |
onValueChange | (value: string) => void | - | Callback when the language changes. |
children | React.ReactNode | - | Selector components (Trigger, Content, Items). |
<CodeBlockLanguageSelectorTrigger />
Trigger button for the language selector dropdown. Pre-styled for code block header.
<CodeBlockLanguageSelectorValue />
Displays the selected language value.
<CodeBlockLanguageSelectorContent />
Dropdown content container. Defaults to align="end".
<CodeBlockLanguageSelectorItem />
Individual language option in the dropdown.
| Prop | Type | Default | Description |
|---|---|---|---|
value | string | - | The language value. |
children | React.ReactNode | - | The display label. |
<CodeBlockContainer />
Low-level container component with performance optimizations (contentVisibility). Used internally by CodeBlock.
<CodeBlockContent />
Low-level component that handles syntax highlighting. Used internally by CodeBlock, but can be used directly for custom layouts.
| Prop | Type | Default | Description |
|---|---|---|---|
code | string | - | The code content to display. |
language | BundledLanguage | - | The programming language for syntax highlighting. |
showLineNumbers | boolean | false | Whether to show line numbers. |
Commit
Display commit information with hash, message, author, and file changes.
The Commit component displays commit details including hash, message, author, timestamp, and changed files.
See scripts/commit.tsx for this example.
Installation
npx ai-elements@latest add commitFeatures
- Commit hash display with copy button
- Author avatar with initials
- Relative timestamp formatting
- Collapsible file changes list
- Color-coded file status (added/modified/deleted/renamed)
- Line additions/deletions count
File Status
| Status | Label | Color |
|---|---|---|
added | A | Green |
modified | M | Yellow |
deleted | D | Red |
renamed | R | Blue |
Props
<Commit />
| Prop | Type | Default | Description |
|---|---|---|---|
...props | React.ComponentProps<typeof Collapsible> | - | Spread to the Collapsible component. |
<CommitHeader />
| Prop | Type | Default | Description |
|---|---|---|---|
...props | React.ComponentProps<typeof CollapsibleTrigger> | - | Spread to the CollapsibleTrigger component. |
<CommitAuthor />
| Prop | Type | Default | Description |
|---|---|---|---|
...props | React.HTMLAttributes<HTMLDivElement> | - | Spread to the container div. |
<CommitAuthorAvatar />
| Prop | Type | Default | Description |
|---|---|---|---|
initials | string | Required | Author initials to display. |
...props | React.ComponentProps<typeof Avatar> | - | Spread to the Avatar component. |
<CommitInfo />
| Prop | Type | Default | Description |
|---|---|---|---|
...props | React.HTMLAttributes<HTMLDivElement> | - | Spread to the container div. |
<CommitMessage />
| Prop | Type | Default | Description |
|---|---|---|---|
...props | React.HTMLAttributes<HTMLSpanElement> | - | Spread to the span element. |
<CommitMetadata />
| Prop | Type | Default | Description |
|---|---|---|---|
...props | React.HTMLAttributes<HTMLDivElement> | - | Spread to the container div. |
<CommitHash />
| Prop | Type | Default | Description |
|---|---|---|---|
...props | React.HTMLAttributes<HTMLSpanElement> | - | Spread to the span element. |
<CommitSeparator />
| Prop | Type | Default | Description |
|---|---|---|---|
children | React.ReactNode | - | Custom separator content. |
...props | React.HTMLAttributes<HTMLSpanElement> | - | Spread to the span element. |
<CommitTimestamp />
| Prop | Type | Default | Description |
|---|---|---|---|
date | Date | Required | Commit date. |
children | React.ReactNode | - | Custom timestamp content. Defaults to relative time. |
...props | React.HTMLAttributes<HTMLTimeElement> | - | Spread to the time element. |
<CommitActions />
| Prop | Type | Default | Description |
|---|---|---|---|
...props | React.HTMLAttributes<HTMLDivElement> | - | Spread to the container div. |
<CommitCopyButton />
| Prop | Type | Default | Description |
|---|---|---|---|
hash | string | Required | Commit hash to copy. |
onCopy | () => void | - | Callback after successful copy. |
onError | (error: Error) => void | - | Callback if copying fails. |
timeout | number | 2000 | Duration to show copied state (ms). |
...props | React.ComponentProps<typeof Button> | - | Spread to the Button component. |
<CommitContent />
| Prop | Type | Default | Description |
|---|---|---|---|
...props | React.ComponentProps<typeof CollapsibleContent> | - | Spread to the CollapsibleContent component. |
<CommitFiles />
| Prop | Type | Default | Description |
|---|---|---|---|
...props | React.HTMLAttributes<HTMLDivElement> | - | Spread to the container div. |
<CommitFile />
| Prop | Type | Default | Description |
|---|---|---|---|
...props | React.HTMLAttributes<HTMLDivElement> | - | Spread to the row div. |
<CommitFileInfo />
| Prop | Type | Default | Description |
|---|---|---|---|
...props | React.HTMLAttributes<HTMLDivElement> | - | Spread to the container div. |
<CommitFileStatus />
| Prop | Type | Default | Description |
|---|---|---|---|
status | unknown | Required | File change status. |
children | React.ReactNode | - | Custom status label. |
...props | React.HTMLAttributes<HTMLSpanElement> | - | Spread to the span element. |
<CommitFileIcon />
| Prop | Type | Default | Description |
|---|---|---|---|
...props | React.ComponentProps<typeof FileIcon> | - | Spread to the FileIcon component. |
<CommitFilePath />
| Prop | Type | Default | Description |
|---|---|---|---|
...props | React.HTMLAttributes<HTMLSpanElement> | - | Spread to the span element. |
<CommitFileChanges />
| Prop | Type | Default | Description |
|---|---|---|---|
...props | React.HTMLAttributes<HTMLDivElement> | - | Spread to the container div. |
<CommitFileAdditions />
| Prop | Type | Default | Description |
|---|---|---|---|
count | number | Required | Number of lines added. |
...props | React.HTMLAttributes<HTMLSpanElement> | - | Spread to the span element. |
<CommitFileDeletions />
| Prop | Type | Default | Description |
|---|---|---|---|
count | number | Required | Number of lines deleted. |
...props | React.HTMLAttributes<HTMLSpanElement> | - | Spread to the span element. |
Confirmation
An alert-based component for managing tool execution approval workflows with request, accept, and reject states.
The Confirmation component provides a flexible system for displaying tool approval requests and their outcomes. Perfect for showing users when AI tools require approval before execution, and displaying the approval status afterward.
See scripts/confirmation.tsx for this example.
Installation
npx ai-elements@latest add confirmationUsage with AI SDK
Build a chat UI with tool approval workflow where dangerous tools require user confirmation before execution.
Add the following component to your frontend:
```tsx title="app/page.tsx" "use client";
import { useChat } from "@ai-sdk/react"; import { DefaultChatTransport, type ToolUIPart } from "ai"; import { useState } from "react"; import { CheckIcon, XIcon } from "lucide-react"; import { Button } from "@/components/ui/button"; import { Confirmation, ConfirmationRequest, ConfirmationAccepted, ConfirmationRejected, ConfirmationActions, ConfirmationAction, } from "@/components/ai-elements/confirmation"; import { MessageResponse } from "@/components/ai-elements/message";
type DeleteFileInput = { filePath: string; confirm: boolean; };
type DeleteFileToolUIPart = ToolUIPart<{ delete_file: { input: DeleteFileInput; output: { success: boolean; message: string }; }; }>;
const Example = () => { const { messages, sendMessage, status, addToolApprovalResponse } = useChat({ transport: new DefaultChatTransport({ api: "/api/chat", }), });
const handleDeleteFile = () => { sendMessage({ text: "Delete the file at /tmp/example.txt" }); };
const latestMessage = messages[messages.length - 1]; const deleteTool = latestMessage?.parts?.find( (part) => part.type === "tool-delete_file" ) as DeleteFileToolUIPart | undefined;
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 space-y-4"> <Button onClick={handleDeleteFile} disabled={status !== "ready"}> Delete Example File </Button>
{deleteTool?.approval && ( <Confirmation approval={deleteTool.approval} state={deleteTool.state}> <ConfirmationRequest> This tool wants to delete:{" "} <code>{deleteTool.input?.filePath}</code> <br /> Do you approve this action? </ConfirmationRequest> <ConfirmationAccepted> <CheckIcon className="size-4" /> <span>You approved this tool execution</span> </ConfirmationAccepted> <ConfirmationRejected> <XIcon className="size-4" /> <span>You rejected this tool execution</span> </ConfirmationRejected> <ConfirmationActions> <ConfirmationAction variant="outline" onClick={() => addToolApprovalResponse({ id: deleteTool.approval!.id, approved: false, }) } > Reject </ConfirmationAction> <ConfirmationAction variant="default" onClick={() => addToolApprovalResponse({ id: deleteTool.approval!.id, approved: true, }) } > Approve </ConfirmationAction> </ConfirmationActions> </Confirmation> )}
{deleteTool?.output && ( <MessageResponse> {deleteTool.output.success ? deleteTool.output.message : Error: ${deleteTool.output.message}} </MessageResponse> )} </div> </div> ); };
export default Example;
Add the following route to your backend:
import { streamText, UIMessage, convertToModelMessages } from "ai"; import { z } from "zod";
// Allow streaming responses up to 30 seconds export const maxDuration = 30;
export async function POST(req: Request) { const { messages }: { messages: UIMessage[] } = await req.json();
const result = streamText({ model: "openai/gpt-4o", messages: await convertToModelMessages(messages), tools: { delete_file: { description: "Delete a file from the file system", parameters: z.object({ filePath: z.string().describe("The path to the file to delete"), confirm: z .boolean() .default(false) .describe("Confirmation that the user wants to delete the file"), }), requireApproval: true, // Enable approval workflow execute: async ({ filePath, confirm }) => { if (!confirm) { return { success: false, message: "Deletion not confirmed", }; }
// Simulate file deletion await new Promise((resolve) => setTimeout(resolve, 500));
return { success: true, message: Successfully deleted ${filePath}, }; }, }, }, });
return result.toUIMessageStreamResponse(); }
## Features
- Context-based state management for approval workflow
- Conditional rendering based on approval state
- Support for approval-requested, approval-responded, output-denied, and output-available states
- Built on shadcn/ui Alert and Button components
- TypeScript support with comprehensive type definitions
- Customizable styling with Tailwind CSS
- Keyboard navigation and accessibility support
- Theme-aware with automatic dark mode support
## Examples
### Approval Request State
Shows the approval request with action buttons when state is `approval-requested`.
See `scripts/confirmation-request.tsx` for this example.
### Approved State
Shows the accepted status when user approves and state is `approval-responded` or `output-available`.
See `scripts/confirmation-accepted.tsx` for this example.
### Rejected State
Shows the rejected status when user rejects and state is `output-denied`.
See `scripts/confirmation-rejected.tsx` for this example.
## Props
### `<Confirmation />`
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| `approval` | `ToolUIPart[` | - | The approval object containing the approval ID and status. If not provided or undefined, the component will not render. |
| `state` | `ToolUIPart[` | - | The current state of the tool (input-streaming, input-available, approval-requested, approval-responded, output-denied, or output-available). Will not render for input-streaming or input-available states. |
| `className` | `string` | - | Additional CSS classes to apply to the Alert component. |
| `...props` | `React.ComponentProps<typeof Alert>` | - | Any other props are spread to the Alert component. |
### `<ConfirmationRequest />`
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| `children` | `React.ReactNode` | - | The content to display when approval is requested. Only renders when state is |
### `<ConfirmationAccepted />`
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| `children` | `React.ReactNode` | - | The content to display when approval is accepted. Only renders when approval.approved is true and state is |
### `<ConfirmationRejected />`
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| `children` | `React.ReactNode` | - | The content to display when approval is rejected. Only renders when approval.approved is false and state is |
### `<ConfirmationActions />`
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| `className` | `string` | - | Additional CSS classes to apply to the actions container. |
| `...props` | `React.ComponentProps<` | - | Any other props are spread to the div element. Only renders when state is |
### `<ConfirmationAction />`
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| `...props` | `React.ComponentProps<typeof Button>` | - | Any other props are spread to the Button component. Styled with h-8 px-3 text-sm classes by default. |
Connection
A custom connection line component for React Flow-based canvases with animated bezier curve styling.
The Connection component provides a styled connection line for React Flow canvases. It renders an animated bezier curve with a circle indicator at the target end, using consistent theming through CSS variables.
Installation
npx ai-elements@latest add connectionFeatures
- Smooth bezier curve animation for connection lines
- Visual indicator circle at the target position
- Theme-aware styling using CSS variables
- Cubic bezier curve calculation for natural flow
- Lightweight implementation with minimal props
- Full TypeScript support with React Flow types
- Compatible with React Flow's connection system
Props
<Connection />
| Prop | Type | Default | Description |
|---|---|---|---|
fromX | number | - | The x-coordinate of the connection start point. |
fromY | number | - | The y-coordinate of the connection start point. |
toX | number | - | The x-coordinate of the connection end point. |
toY | number | - | The y-coordinate of the connection end point. |
Context
A compound component system for displaying AI model context window usage, token consumption, and cost estimation.
The Context component provides a comprehensive view of AI model usage through a compound component system. It displays context window utilization, token consumption breakdown (input, output, reasoning, cache), and cost estimation in an interactive hover card interface.
See scripts/context.tsx for this example.
Installation
npx ai-elements@latest add contextFeatures
- Compound Component Architecture: Flexible composition of context display elements
- Visual Progress Indicator: Circular SVG progress ring showing context usage percentage
- Token Breakdown: Detailed view of input, output, reasoning, and cached tokens
- Cost Estimation: Real-time cost calculation using the
tokenlenslibrary - Intelligent Formatting: Automatic token count formatting (K, M, B suffixes)
- Interactive Hover Card: Detailed information revealed on hover
- Context Provider Pattern: Clean data flow through React Context API
- TypeScript Support: Full type definitions for all components
- Accessible Design: Proper ARIA labels and semantic HTML
- Theme Integration: Uses currentColor for automatic theme adaptation
Props
<Context />
| Prop | Type | Default | Description |
|---|---|---|---|
maxTokens | number | - | The total context window size in tokens. |
usedTokens | number | - | The number of tokens currently used. |
usage | LanguageModelUsage | - | Detailed token usage breakdown from the AI SDK (input, output, reasoning, cached tokens). |
modelId | ModelId | - | Model identifier for cost calculation (e.g., |
...props | ComponentProps<HoverCard> | - | Any other props are spread to the HoverCard component. |
<ContextTrigger />
| Prop | Type | Default | Description |
|---|---|---|---|
children | React.ReactNode | - | Custom trigger element. If not provided, renders a default button with percentage and icon. |
...props | ComponentProps<Button> | - | Props spread to the default button element. |
<ContextContent />
| Prop | Type | Default | Description |
|---|---|---|---|
className | string | - | Additional CSS classes for the hover card content. |
...props | ComponentProps<HoverCardContent> | - | Props spread to the HoverCardContent component. |
<ContextContentHeader />
| Prop | Type | Default | Description |
|---|---|---|---|
children | React.ReactNode | - | Custom header content. If not provided, renders percentage and token count with progress bar. |
...props | ComponentProps<div> | - | Props spread to the header div element. |
<ContextContentBody />
| Prop | Type | Default | Description |
|---|---|---|---|
children | React.ReactNode | - | Body content, typically containing usage breakdown components. |
...props | ComponentProps<div> | - | Props spread to the body div element. |
<ContextContentFooter />
| Prop | Type | Default | Description |
|---|---|---|---|
children | React.ReactNode | - | Custom footer content. If not provided, renders total cost when modelId is provided. |
...props | ComponentProps<div> | - | Props spread to the footer div element. |
Usage Components
All usage components (ContextInputUsage, ContextOutputUsage, ContextReasoningUsage, ContextCacheUsage) share the same props:
| Prop | Type | Default | Description |
|---|---|---|---|
children | React.ReactNode | - | Custom content. If not provided, renders token count and cost for the respective usage type. |
className | string | - | Additional CSS classes. |
...props | ComponentProps<div> | - | Props spread to the div element. |
Component Architecture
The Context component uses a compound component pattern with React Context for data sharing:
1. `<Context>` - Root provider component that holds all context data 2. `<ContextTrigger>` - Interactive trigger element (default: button with percentage) 3. `<ContextContent>` - Hover card content container 4. `<ContextContentHeader>` - Header section with progress visualization 5. `<ContextContentBody>` - Body section for usage breakdowns 6. `<ContextContentFooter>` - Footer section for total cost 7. Usage Components - Individual token usage displays (Input, Output, Reasoning, Cache)
Token Formatting
The component uses Intl.NumberFormat with compact notation for automatic formatting:
- Under 1,000: Shows exact count (e.g., "842")
- 1,000+: Shows with K suffix (e.g., "32K")
- 1,000,000+: Shows with M suffix (e.g., "1.5M")
- 1,000,000,000+: Shows with B suffix (e.g., "2.1B")
Cost Calculation
When a modelId is provided, the component automatically calculates costs using the tokenlens library:
- Input tokens: Cost based on model's input pricing
- Output tokens: Cost based on model's output pricing
- Reasoning tokens: Special pricing for reasoning-capable models
- Cached tokens: Reduced pricing for cached input tokens
- Total cost: Sum of all token type costs
Costs are formatted using Intl.NumberFormat with USD currency.
Styling
The component uses Tailwind CSS classes and follows your design system:
- Progress indicator uses
currentColorfor theme adaptation - Hover card has customizable width and padding
- Footer has a secondary background for visual separation
- All text sizes use the
text-xsclass for consistency - Muted foreground colors for secondary information
Controls
A styled controls component for React Flow-based canvases with zoom and fit view functionality.
The Controls component provides interactive zoom and fit view controls for React Flow canvases. It includes a modern, themed design with backdrop blur and card styling.
Installation
npx ai-elements@latest add controlsFeatures
- Zoom in/out controls
- Fit view button to center and scale content
- Rounded pill design with backdrop blur
- Theme-aware card background
- Subtle drop shadow for depth
- Full TypeScript support
- Compatible with all React Flow control features
Props
<Controls />
| Prop | Type | Default | Description |
|---|---|---|---|
className | string | - | Additional CSS classes to apply to the controls. |
...props | ComponentProps<typeof Controls> | - | Any other props from @xyflow/react Controls component (showZoom, showFitView, showInteractive, position, etc.). |
Conversation
Wraps messages and automatically scrolls to the bottom. Also includes a scroll button that appears when not at the bottom.
The Conversation component wraps messages and automatically scrolls to the bottom. Also includes a scroll button that appears when not at the bottom.
<Preview path="conversation" className="p-0" />
Installation
npx ai-elements@latest add conversationUsage with AI SDK
Build a simple conversational UI with Conversation and `PromptInput`:
Add the following component to your frontend:
```tsx title="app/page.tsx" "use client";
import { Conversation, ConversationContent, ConversationDownload, ConversationEmptyState, ConversationScrollButton, } from "@/components/ai-elements/conversation"; import { Message, MessageContent, MessageResponse, } from "@/components/ai-elements/message"; import { Input, PromptInputTextarea, PromptInputSubmit, } from "@/components/ai-elements/prompt-input"; import { MessageSquare } from "lucide-react"; import { useState } from "react"; import { useChat } from "@ai-sdk/react";
const ConversationDemo = () => { const [input, setInput] = useState(""); const { messages, sendMessage, status } = 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.length === 0 ? ( <ConversationEmptyState icon={<MessageSquare className="size-12" />} title="Start a conversation" description="Type a message below to begin chatting" /> ) : ( messages.map((message) => ( <Message from={message.role} key={message.id}> <MessageContent> {message.parts.map((part, i) => { switch (part.type) { case "text": // we don't use any reasoning or tool calls in this example return ( <MessageResponse key={${message.id}-${i}}> {part.text} </MessageResponse> ); default: return null; } })} </MessageContent> </Message> )) )} </ConversationContent> <ConversationDownload messages={messages} /> <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 ConversationDemo;
Add the following route to your backend:
import { streamText, UIMessage, convertToModelMessages } from "ai";
// Allow streaming responses up to 30 seconds export const maxDuration = 30;
export async function POST(req: Request) { const { messages }: { messages: UIMessage[] } = await req.json();
const result = streamText({ model: "openai/gpt-4o", messages: await convertToModelMessages(messages), });
return result.toUIMessageStreamResponse(); }
## Features
- Automatic scrolling to the bottom when new messages are added
- Smooth scrolling behavior with configurable animation
- Scroll button that appears when not at the bottom
- Download conversation as Markdown
- Responsive design with customizable padding and spacing
- Flexible content layout with consistent message spacing
- Accessible with proper ARIA roles for screen readers
- Customizable styling through className prop
- Support for any number of child message components
## Props
### `<Conversation />`
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| `contextRef` | `React.Ref<StickToBottomContext>` | - | Optional ref to access the StickToBottom context object. |
| `instance` | `StickToBottomInstance` | - | Optional instance for controlling the StickToBottom component. |
| `children` | `((context: StickToBottomContext) => ReactNode) | ReactNode` | - | Render prop or ReactNode for custom rendering with context. |
| `...props` | `Omit<React.HTMLAttributes<HTMLDivElement>, ` | - | Any other props are spread to the root div. |
### `<ConversationContent />`
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| `children` | `((context: StickToBottomContext) => ReactNode) | ReactNode` | - | Render prop or ReactNode for custom rendering with context. |
| `...props` | `Omit<React.HTMLAttributes<HTMLDivElement>, ` | - | Any other props are spread to the root div. |
### `<ConversationEmptyState />`
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| `title` | `string` | - | The title text to display. |
| `description` | `string` | - | The description text to display. |
| `icon` | `React.ReactNode` | - | Optional icon to display above the text. |
| `children` | `React.ReactNode` | - | Optional additional content to render below the text. |
| `...props` | `ComponentProps<` | - | Any other props are spread to the root div. |
### `<ConversationScrollButton />`
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| `...props` | `ComponentProps<typeof Button>` | - | Any other props are spread to the underlying shadcn/ui Button component. |
### `<ConversationDownload />`
A button that downloads the conversation as a Markdown file.
import { ConversationDownload } from "@/components/ai-elements/conversation";
<Conversation> <ConversationContent> {messages.map(...)} </ConversationContent> <ConversationDownload messages={messages} /> <ConversationScrollButton /> </Conversation>
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| `messages` | `ConversationMessage[]` | Required | Array of messages to include in the download. |
| `filename` | `string` | - | The filename for the downloaded file. |
| `formatMessage` | `(message: ConversationMessage, index: number) => string` | - | Custom function to format each message in the output. |
| `...props` | `Omit<ComponentProps<typeof Button>, ` | - | Any other props are spread to the underlying shadcn/ui Button component. |
### `messagesToMarkdown`
A utility function to convert messages to Markdown format. Useful for custom download implementations.
import { messagesToMarkdown } from "@/components/ai-elements/conversation";
const markdown = messagesToMarkdown(messages);
// With custom formatter const customMarkdown = messagesToMarkdown( messages, (msg, i) => [${msg.role}]: ${msg.content} );
Edge
Customizable edge components for React Flow canvases with animated and temporary states.
The Edge component provides two pre-styled edge types for React Flow canvases: Temporary for dashed temporary connections and Animated for connections with animated indicators.
Installation
npx ai-elements@latest add edgeFeatures
- Two distinct edge types: Temporary and Animated
- Temporary edges use dashed lines with ring color
- Animated edges include a moving circle indicator
- Automatic handle position calculation
- Smart offset calculation based on handle type and position
- Uses Bezier curves for smooth, natural-looking connections
- Fully compatible with React Flow's edge system
- Type-safe implementation with TypeScript
Edge Types
Edge.Temporary
A dashed edge style for temporary or preview connections. Uses a simple Bezier path with a dashed stroke pattern.
Edge.Animated
A solid edge with an animated circle that moves along the path. The animation repeats indefinitely with a 2-second duration, providing visual feedback for active connections.
Props
Both edge types accept standard React Flow EdgeProps:
| Prop | Type | Default | Description |
|---|---|---|---|
id | string | - | Unique identifier for the edge. |
source | string | - | ID of the source node. |
target | string | - | ID of the target node. |
sourceX | number | - | X coordinate of the source handle (Temporary only). |
sourceY | number | - | Y coordinate of the source handle (Temporary only). |
targetX | number | - | X coordinate of the target handle (Temporary only). |
targetY | number | - | Y coordinate of the target handle (Temporary only). |
sourcePosition | Position | - | Position of the source handle (Left, Right, Top, Bottom). |
targetPosition | Position | - | Position of the target handle (Left, Right, Top, Bottom). |
markerEnd | string | - | SVG marker ID for the edge end (Animated only). |
style | React.CSSProperties | - | Custom styles for the edge (Animated only). |
Environment Variables
Display environment variables with masking and copy functionality.
The EnvironmentVariables component displays environment variables with value masking, visibility toggle, and copy functionality.
See scripts/environment-variables.tsx for this example.
Installation
npx ai-elements@latest add environment-variablesFeatures
- Value masking by default
- Toggle visibility switch
- Copy individual values
- Export format support (
export KEY="value") - Required badge indicator
Props
<EnvironmentVariables />
| Prop | Type | Default | Description |
|---|---|---|---|
showValues | boolean | - | Controlled visibility state. |
defaultShowValues | boolean | false | Default visibility state. |
onShowValuesChange | (show: boolean) => void | - | Callback when visibility changes. |
...props | React.HTMLAttributes<HTMLDivElement> | - | Spread to the container div. |
<EnvironmentVariablesHeader />
| Prop | Type | Default | Description |
|---|---|---|---|
...props | React.HTMLAttributes<HTMLDivElement> | - | Spread to the header div. |
<EnvironmentVariablesTitle />
| Prop | Type | Default | Description |
|---|---|---|---|
children | React.ReactNode | - | Custom title text. |
...props | React.HTMLAttributes<HTMLHeadingElement> | - | Spread to the h3 element. |
<EnvironmentVariablesToggle />
| Prop | Type | Default | Description |
|---|---|---|---|
...props | React.ComponentProps<typeof Switch> | - | Spread to the Switch component. |
<EnvironmentVariablesContent />
| Prop | Type | Default | Description |
|---|---|---|---|
...props | React.HTMLAttributes<HTMLDivElement> | - | Spread to the content div. |
<EnvironmentVariable />
| Prop | Type | Default | Description |
|---|---|---|---|
name | string | Required | Variable name. |
value | string | Required | Variable value. |
...props | React.HTMLAttributes<HTMLDivElement> | - | Spread to the row div. |
<EnvironmentVariableGroup />
| Prop | Type | Default | Description |
|---|---|---|---|
...props | React.HTMLAttributes<HTMLDivElement> | - | Spread to the group div. |
<EnvironmentVariableName />
| Prop | Type | Default | Description |
|---|---|---|---|
children | React.ReactNode | - | Custom name content. Defaults to the name from context. |
...props | React.HTMLAttributes<HTMLSpanElement> | - | Spread to the span element. |
<EnvironmentVariableValue />
| Prop | Type | Default | Description |
|---|---|---|---|
children | React.ReactNode | - | Custom value content. Defaults to the masked/unmasked value from context. |
...props | React.HTMLAttributes<HTMLSpanElement> | - | Spread to the span element. |
<EnvironmentVariableCopyButton />
| Prop | Type | Default | Description |
|---|---|---|---|
copyFormat | unknown | - | Format to copy. |
onCopy | () => void | - | Callback after successful copy. |
onError | (error: Error) => void | - | Callback if copying fails. |
timeout | number | 2000 | Duration to show copied state (ms). |
...props | React.ComponentProps<typeof Button> | - | Spread to the Button component. |
<EnvironmentVariableRequired />
| Prop | Type | Default | Description |
|---|---|---|---|
children | React.ReactNode | - | Custom badge text. |
...props | React.ComponentProps<typeof Badge> | - | Spread to the Badge component. |
File Tree
Display hierarchical file and folder structure with expand/collapse functionality.
The FileTree component displays a hierarchical file system structure with expandable folders and file selection.
See scripts/file-tree.tsx for this example.
Installation
npx ai-elements@latest add file-treeFeatures
- Hierarchical folder structure
- Expand/collapse folders
- File selection with callback
- Keyboard accessible
- Customizable icons
- Controlled and uncontrolled modes
Examples
Basic Usage
See scripts/file-tree-basic.tsx for this example.
With Selection
See scripts/file-tree-selection.tsx for this example.
Default Expanded
See scripts/file-tree-expanded.tsx for this example.
Props
<FileTree />
| Prop | Type | Default | Description |
|---|---|---|---|
expanded | Set<string> | - | Controlled expanded paths. |
defaultExpanded | Set<string> | new Set() | Default expanded paths. |
selectedPath | string | - | Currently selected file/folder path. |
onSelect | (path: string) => void | - | Callback when a file/folder is selected. |
onExpandedChange | (expanded: Set<string>) => void | - | Callback when expanded paths change. |
className | string | - | Additional CSS classes. |
<FileTreeFolder />
| Prop | Type | Default | Description |
|---|---|---|---|
path | string | - | Unique folder path. |
name | string | - | Display name. |
className | string | - | Additional CSS classes. |
<FileTreeFile />
| Prop | Type | Default | Description |
|---|---|---|---|
path | string | - | Unique file path. |
name | string | - | Display name. |
icon | ReactNode | - | Custom file icon. |
className | string | - | Additional CSS classes. |
Subcomponents
FileTreeIcon- Icon wrapperFileTreeName- Name textFileTreeActions- Action buttons container (stops click propagation)
Image
Displays AI-generated images from the AI SDK.
The Image component displays AI-generated images from the AI SDK. It accepts a `Experimental_GeneratedImage` object from the AI SDK's generateImage function and automatically renders it as an image.
See scripts/image.tsx for this example.
Installation
npx ai-elements@latest add imageUsage with AI SDK
Build a simple app allowing a user to generate an image given a prompt.
Install the @ai-sdk/openai package:
npm i @ai-sdk/openaiAdd the following component to your frontend:
```tsx title="app/page.tsx" "use client";
import { Image } from "@/components/ai-elements/image"; import { Input, PromptInputTextarea, PromptInputSubmit, } from "@/components/ai-elements/prompt-input"; import { useState } from "react"; import { Spinner } from "@/components/ui/spinner";
const ImageDemo = () => { const [prompt, setPrompt] = useState("A futuristic cityscape at sunset"); const [imageData, setImageData] = useState<any>(null); const [isLoading, setIsLoading] = useState(false);
const handleSubmit = async (e: React.FormEvent) => { e.preventDefault(); if (!prompt.trim()) return; setPrompt("");
setIsLoading(true); try { const response = await fetch("/api/image", { method: "POST", body: JSON.stringify({ prompt: prompt.trim() }), });
const data = await response.json();
setImageData(data); } catch (error) { console.error("Error generating image:", error); } finally { setIsLoading(false); } };
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"> <div className="flex-1 overflow-y-auto p-4"> {imageData && ( <div className="flex justify-center"> <Image {...imageData} alt="Generated image" className="h-[300px] aspect-square border rounded-lg" /> </div> )} {isLoading && <Spinner />} </div>
<Input onSubmit={handleSubmit} className="mt-4 w-full max-w-2xl mx-auto relative" > <PromptInputTextarea value={prompt} placeholder="Describe the image you want to generate..." onChange={(e) => setPrompt(e.currentTarget.value)} className="pr-12" /> <PromptInputSubmit status={isLoading ? "submitted" : "ready"} disabled={!prompt.trim()} className="absolute bottom-1 right-1" /> </Input> </div> </div> ); };
export default ImageDemo;
Add the following route to your backend:
import { openai } from "@ai-sdk/openai"; import { experimental_generateImage } from "ai";
export async function POST(req: Request) { const { prompt }: { prompt: string } = await req.json();
const { image } = await experimental_generateImage({ model: openai.image("dall-e-3"), prompt: prompt, size: "1024x1024", });
return Response.json({ base64: image.base64, uint8Array: image.uint8Array, mediaType: image.mediaType, }); }
## Features
- Accepts `Experimental_GeneratedImage` objects directly from the AI SDK
- Automatically creates proper data URLs from base64-encoded image data
- Supports all standard HTML image attributes
- Responsive by default with `max-w-full h-auto` styling
- Customizable with additional CSS classes
- Includes proper TypeScript types for AI SDK compatibility
## Props
### `<Image />`
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| `alt` | `string` | - | Alternative text for the image. |
| `className` | `string` | - | Additional CSS classes to apply to the image. |
| `...props` | `Experimental_GeneratedImage` | - | The image data to display, as returned by the AI SDK. |
Inline Citation
A hoverable citation component that displays source information and quotes inline with text, perfect for AI-generated content with references.
The InlineCitation component provides a way to display citations inline with text content, similar to academic papers or research documents. It consists of a citation pill that shows detailed source information on hover, making it perfect for AI-generated content that needs to reference sources.
See scripts/inline-citation.tsx for this example.
Installation
npx ai-elements@latest add inline-citationUsage with AI SDK
Build citations for AI-generated content using `experimental_generateObject`.
Add the following component to your frontend:
```tsx title="app/page.tsx" "use client";
import { experimental_useObject as useObject } from "@ai-sdk/react"; import { InlineCitation, InlineCitationText, InlineCitationCard, InlineCitationCardTrigger, InlineCitationCardBody, InlineCitationCarousel, InlineCitationCarouselContent, InlineCitationCarouselItem, InlineCitationCarouselHeader, InlineCitationCarouselIndex, InlineCitationCarouselPrev, InlineCitationCarouselNext, InlineCitationSource, InlineCitationQuote, } from "@/components/ai-elements/inline-citation"; import { Button } from "@/components/ui/button"; import { citationSchema } from "@/app/api/citation/route";
const CitationDemo = () => { const { object, submit, isLoading } = useObject({ api: "/api/citation", schema: citationSchema, });
const handleSubmit = (topic: string) => { submit({ prompt: topic }); };
return ( <div className="max-w-4xl mx-auto p-6 space-y-6"> <div className="flex gap-2 mb-6"> <Button onClick={() => handleSubmit("artificial intelligence")} disabled={isLoading} variant="outline" > Generate AI Content </Button> <Button onClick={() => handleSubmit("climate change")} disabled={isLoading} variant="outline" > Generate Climate Content </Button> </div>
{isLoading && !object && ( <div className="text-muted-foreground"> Generating content with citations... </div> )}
{object?.content && ( <div className="prose prose-sm max-w-none"> <p className="leading-relaxed"> {object.content.split(/(\[\d+\])/).map((part, index) => { const citationMatch = part.match(/\[(\d+)\]/); if (citationMatch) { const citationNumber = citationMatch[1]; const citation = object.citations?.find( (c: any) => c.number === citationNumber );
if (citation) { return ( <InlineCitation key={index}> <InlineCitationCard> <InlineCitationCardTrigger sources={[citation.url]} /> <InlineCitationCardBody> <InlineCitationCarousel> <InlineCitationCarouselHeader> <InlineCitationCarouselPrev /> <InlineCitationCarouselNext /> <InlineCitationCarouselIndex /> </InlineCitationCarouselHeader> <InlineCitationCarouselContent> <InlineCitationCarouselItem> <InlineCitationSource title={citation.title} url={citation.url} description={citation.description} /> {citation.quote && ( <InlineCitationQuote> {citation.quote} </InlineCitationQuote> )} </InlineCitationCarouselItem> </InlineCitationCarouselContent> </InlineCitationCarousel> </InlineCitationCardBody> </InlineCitationCard> </InlineCitation> ); } } return part; })} </p> </div> )} </div> ); };
export default CitationDemo;
Add the following route to your backend:
import { streamObject } from "ai"; import { z } from "zod";
export const citationSchema = z.object({ content: z.string(), citations: z.array( z.object({ number: z.string(), title: z.string(), url: z.string(), description: z.string().optional(), quote: z.string().optional(), }) ), });
// Allow streaming responses up to 30 seconds export const maxDuration = 30;
export async function POST(req: Request) { const { prompt } = await req.json();
const result = streamObject({ model: "openai/gpt-4o", schema: citationSchema, prompt: `Generate a well-researched paragraph about ${prompt} with proper citations.
Include:
- A comprehensive paragraph with inline citations marked as [1], [2], etc.
- 2-3 citations with realistic source information
- Each citation should have a title, URL, and optional description/quote
- Make the content informative and the sources credible
Format citations as numbered references within the text.`, });
return result.toTextStreamResponse(); }
## Features
- Hover interaction to reveal detailed citation information
- **Carousel navigation** for multiple citations with prev/next controls
- **Live index tracking** showing current slide position (e.g., "1/5")
- Support for source titles, URLs, and descriptions
- Optional quote blocks for relevant excerpts
- Composable architecture for flexible citation formats
- Accessible design with proper keyboard navigation
- Seamless integration with AI-generated content
- Clean visual design that doesn't disrupt reading flow
- Smart badge display showing source hostname and count
## Usage with AI SDK
Currently, there is no official support for inline citations with Streamdown or the Response component. This is because:
- There isn't any good markdown syntax for inline citations
- Language models don't naturally respond with inline citation syntax
- The AI SDK doesn't have built-in support for inline citations
### Potential Approaches
While these methods are hypothetical and not officially supported, there are two conceptual ways inline citations could work with Streamdown:
1. **Footnote conversion**: GitHub Flavored Markdown (GFM) handles footnotes using `[^1]` syntax. You could hypothetically remove the default footnote rendering and convert footnotes to inline citations instead.
2. **Custom HTML syntax**: You could add a system prompt instructing the model to use a special HTML syntax like `<citation />` and pass that as a custom component to Streamdown.
These approaches require custom implementation and are not currently supported out of the box. We will investigate official support for this use case in the future.
For now, the recommended approach is to use `experimental_useObject` (as shown in the usage example above) to generate structured citation data, then manually parse and render inline citations.
## Props
### `<InlineCitation />`
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| `...props` | `React.ComponentProps<` | - | Any other props are spread to the root span element. |
### `<InlineCitationText />`
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| `...props` | `React.ComponentProps<` | - | Any other props are spread to the underlying span element. |
### `<InlineCitationCard />`
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| `...props` | `React.ComponentProps<` | - | Any other props are spread to the HoverCard component. |
### `<InlineCitationCardTrigger />`
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| `sources` | `string[]` | - | Array of source URLs. The length determines the number displayed in the badge. |
| `...props` | `React.ComponentProps<` | - | Any other props are spread to the underlying button element. |
### `<InlineCitationCardBody />`
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| `...props` | `React.ComponentProps<` | - | Any other props are spread to the underlying div. |
### `<InlineCitationCarousel />`
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| `...props` | `React.ComponentProps<typeof Carousel>` | - | Any other props are spread to the underlying Carousel component. |
### `<InlineCitationCarouselContent />`
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| `...props` | `React.ComponentProps<` | - | Any other props are spread to the underlying CarouselContent component. |
### `<InlineCitationCarouselItem />`
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| `...props` | `React.ComponentProps<` | - | Any other props are spread to the underlying div. |
### `<InlineCitationCarouselHeader />`
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| `...props` | `React.ComponentProps<` | - | Any other props are spread to the underlying div. |
### `<InlineCitationCarouselIndex />`
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| `...props` | `React.ComponentProps<` | - | Any other props are spread to the underlying div. Children will override the default index display. |
### `<InlineCitationCarouselPrev />`
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| `...props` | `React.ComponentProps<typeof CarouselPrevious>` | - | Any other props are spread to the underlying CarouselPrevious component. |
### `<InlineCitationCarouselNext />`
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| `...props` | `React.ComponentProps<typeof CarouselNext>` | - | Any other props are spread to the underlying CarouselNext component. |
### `<InlineCitationSource />`
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| `title` | `string` | - | The title of the source. |
| `url` | `string` | - | The URL of the source. |
| `description` | `string` | - | A brief description of the source. |
| `...props` | `React.ComponentProps<` | - | Any other props are spread to the underlying div. |
### `<InlineCitationQuote />`
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| `...props` | `React.ComponentProps<` | - | Any other props are spread to the underlying blockquote element. |
JSX Preview
A component that dynamically renders JSX strings with streaming support for AI-generated UI.
The JSXPreview component renders JSX strings dynamically, supporting streaming scenarios where JSX may be incomplete. It automatically closes unclosed tags during streaming, making it ideal for displaying AI-generated UI components in real-time.
See scripts/jsx-preview.tsx for this example.
Installation
npx ai-elements@latest add jsx-previewFeatures
- Renders JSX strings dynamically using
react-jsx-parser - Streaming support with automatic tag completion
- Custom component injection for rendering your own components
- Error handling with customizable error display
- Context-based architecture for flexible composition
Usage with AI SDK
The JSXPreview component integrates with the AI SDK to render generated UI in real-time:
```tsx title="components/generated-ui.tsx" "use client";
import { JSXPreview, JSXPreviewContent, JSXPreviewError, } from "@/components/ai-elements/jsx-preview";
type GeneratedUIProps = { jsx: string; isStreaming: boolean; };
export const GeneratedUI = ({ jsx, isStreaming }: GeneratedUIProps) => ( <JSXPreview jsx={jsx} isStreaming={isStreaming} onError={(error) => console.error("JSX Parse Error:", error)} > <JSXPreviewContent /> <JSXPreviewError /> </JSXPreview> );
### With Custom Components
You can inject custom components to be used within the rendered JSX:
"use client";
import { JSXPreview, JSXPreviewContent, } from "@/components/ai-elements/jsx-preview"; import { Button } from "@/components/ui/button"; import { Card } from "@/components/ui/card";
const customComponents = { Button, Card, };
export const GeneratedUIWithComponents = ({ jsx }: { jsx: string }) => ( <JSXPreview jsx={jsx} components={customComponents}> <JSXPreviewContent /> </JSXPreview> );
## Props
### `<JSXPreview />`
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| `jsx` | `string` | Required | The JSX string to render. |
| `isStreaming` | `boolean` | `false` | When true, automatically completes unclosed tags. |
| `components` | `Record<string, React.ComponentType>` | - | Custom components available within the rendered JSX. |
| `bindings` | `Record<string, unknown>` | - | Variables and functions available within the JSX scope. |
| `onError` | `(error: Error) => void` | - | Callback fired when a parsing or rendering error occurs. |
| `...props` | `React.ComponentProps<` | - | Any other props are spread to the underlying div element. |
### `<JSXPreviewContent />`
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| `renderError` | `JsxParserProps[` | - | Custom error renderer passed to react-jsx-parser. |
| `...props` | `React.ComponentProps<` | - | Any other props are spread to the underlying div element. |
### `<JSXPreviewError />`
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| `children` | `ReactNode | ((error: Error) => ReactNode)` | - | Custom error content or render function receiving the error. |
| `...props` | `React.ComponentProps<` | - | Any other props are spread to the underlying div element. |
Message
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.
See scripts/message.tsx for this example.
Installation
npx ai-elements@latest add messageFeatures
- Displays messages from both user and AI assistant with distinct styling and automatic alignment
- Minimalist flat design with user messages in secondary background and assistant messages full-width
- Response branching with navigation controls to switch between multiple AI response versions
- Markdown rendering with GFM support (tables, task lists, strikethrough), math equations, and smart streaming
- Action buttons for common operations (retry, like, dislike, copy, share) with tooltips and state management
- File attachments display with support for images and generic files with preview and remove functionality
- Code blocks with syntax highlighting and copy-to-clipboard functionality
- Keyboard accessible with proper ARIA labels
- Responsive design that adapts to different screen sizes
- Seamless light/dark theme integration
Usage with AI SDK
Build a simple chat UI where the user can copy or regenerate the most recent message.
Add the following component to your frontend:
```tsx title="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;
## Props
### `<Message />`
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| `from` | `UIMessage[` | - | The role of the message sender ( |
| `...props` | `React.HTMLAttributes<HTMLDivElement>` | - | Any other props are spread to the root div. |
### `<MessageContent />`
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| `...props` | `React.HTMLAttributes<HTMLDivElement>` | - | Any other props are spread to the content div. |
### `<MessageResponse />`
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| `children` | `string` | - | The markdown content to render. |
| `parseIncompleteMarkdown` | `boolean` | `true` | Whether to parse and fix incomplete markdown syntax (e.g., unclosed code blocks or lists). |
| `className` | `string` | - | CSS class names to apply to the wrapper div element. |
| `components` | `object` | - | Custom React components to use for rendering markdown elements (e.g., custom heading, paragraph, code block components). |
| `allowedImagePrefixes` | `string[]` | `[` | Array of allowed URL prefixes for images. Use [ |
| `allowedLinkPrefixes` | `string[]` | `[` | Array of allowed URL prefixes for links. Use [ |
| `defaultOrigin` | `string` | - | Default origin to use for relative URLs in links and images. |
| `rehypePlugins` | `array` | `[rehypeKatex]` | Array of rehype plugins to use for processing HTML. Includes KaTeX for math rendering by default. |
| `remarkPlugins` | `array` | `[remarkGfm, remarkMath]` | Array of remark plugins to use for processing markdown. Includes GitHub Flavored Markdown and math support by default. |
| `...props` | `React.HTMLAttributes<HTMLDivElement>` | - | Any other props are spread to the root div. |
### `<MessageActions />`
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| `...props` | `React.HTMLAttributes<HTMLDivElement>` | - | HTML attributes to spread to the root div. |
### `<MessageAction />`
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| `tooltip` | `string` | - | Optional tooltip text shown on hover. |
| `label` | `string` | - | Accessible label for screen readers. Also used as fallback if tooltip is not provided. |
| `...props` | `React.ComponentProps<typeof Button>` | - | Any other props are spread to the underlying shadcn/ui Button component. |
### `<MessageBranch />`
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| `defaultBranch` | `number` | `0` | The index of the branch to show by default. |
| `onBranchChange` | `(branchIndex: number) => void` | - | Callback fired when the branch changes. |
| `...props` | `React.HTMLAttributes<HTMLDivElement>` | - | Any other props are spread to the root div. |
### `<MessageBranchContent />`
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| `...props` | `React.HTMLAttributes<HTMLDivElement>` | - | Any other props are spread to the root div. |
### `<MessageBranchSelector />`
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| `from` | `UIMessage[` | - | Aligns the selector for user, assistant or system messages. |
| `...props` | `React.HTMLAttributes<HTMLDivElement>` | - | Any other props are spread to the selector container. |
### `<MessageBranchPrevious />`
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| `...props` | `React.ComponentProps<typeof Button>` | - | Any other props are spread to the underlying shadcn/ui Button component. |
### `<MessageBranchNext />`
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| `...props` | `React.ComponentProps<typeof Button>` | - | Any other props are spread to the underlying shadcn/ui Button component. |
### `<MessageBranchPage />`
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| `...props` | `React.HTMLAttributes<HTMLSpanElement>` | - | Any other props are spread to the underlying span element. |
### `<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 | Default | Description |
|------|------|---------|-------------|
| `children` | `ReactNode` | - | MessageAttachment components to render. Returns null if no children provided. |
| `...props` | `React.ComponentProps<` | - | Any other props are spread to the root 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 | Default | Description |
|------|------|---------|-------------|
| `data` | `FileUIPart` | - | The file data to display. Must include url and mediaType. |
| `onRemove` | `() => void` | - | Optional callback fired when the remove button is clicked. If provided, a remove button will appear on hover. |
| `...props` | `React.HTMLAttributes<HTMLDivElement>` | - | Any other props are spread to the root div. |
**Example:**
<MessageAttachment data={{ type: "file", url: "https://example.com/image.jpg", mediaType: "image/jpeg", filename: "image.jpg", }} onRemove={() => console.log("Remove clicked")} />
Mic Selector
A composable dropdown component for selecting audio input devices with permission handling and device change detection.
The MicSelector component provides a flexible and composable interface for selecting microphone input devices. Built on shadcn/ui's Command and Popover components, it features automatic device detection, permission handling, dynamic device list updates, and intelligent device name parsing.
See scripts/mic-selector.tsx for this example.
Installation
npx ai-elements@latest add mic-selectorFeatures
- Fully composable architecture with granular control components
- Automatic audio input device enumeration
- Permission-based device name display
- Real-time device change detection via devicechange events
- Intelligent device label parsing with ID extraction
- Controlled and uncontrolled component patterns
- Responsive width matching between trigger and content
- Built on shadcn/ui Command and Popover components
- Full TypeScript support with proper types for all components
Props
<MicSelector />
Root Popover component that provides context for all child components.
| Prop | Type | Default | Description |
|---|---|---|---|
defaultValue | string | - | The default selected device ID (uncontrolled). |
value | string | - | The selected device ID (controlled). |
onValueChange | (deviceId: string) => void | - | Callback fired when the selected device changes. |
defaultOpen | boolean | false | The default open state (uncontrolled). |
open | boolean | - | The open state (controlled). |
onOpenChange | (open: boolean) => void | - | Callback fired when the open state changes. Automatically requests microphone permission when opened without permission. |
...props | React.ComponentProps<typeof Popover> | - | Any other props are spread to the Popover component. |
<MicSelectorTrigger />
Button that opens the microphone selector popover. Automatically tracks its width to match the popover content.
| Prop | Type | Default | Description |
|---|---|---|---|
...props | React.ComponentProps<typeof Button> | - | Any other props are spread to the Button component. |
<MicSelectorValue />
Displays the currently selected microphone name or a placeholder.
| Prop | Type | Default | Description |
|---|---|---|---|
...props | React.ComponentProps< | - | Any other props are spread to the span element. |
<MicSelectorContent />
Container for the Command component, rendered inside the popover.
| Prop | Type | Default | Description |
|---|---|---|---|
popoverOptions | React.ComponentProps<typeof PopoverContent> | - | Props to pass to the underlying PopoverContent component. |
...props | React.ComponentProps<typeof Command> | - | Any other props are spread to the Command component. |
<MicSelectorInput />
Search input for filtering microphones.
| Prop | Type | Default | Description |
|---|---|---|---|
...props | React.ComponentProps<typeof CommandInput> | - | Any other props are spread to the CommandInput component. |
<MicSelectorList />
Wrapper for the list of microphone items. Uses render props pattern to provide access to device data.
| Prop | Type | Default | Description |
|---|---|---|---|
children | (devices: MediaDeviceInfo[]) => ReactNode | - | Render function that receives the array of available devices. |
...props | Omit<React.ComponentProps<typeof CommandList>, | - | Any other props are spread to the CommandList component. |
<MicSelectorEmpty />
Message shown when no microphones match the search.
| Prop | Type | Default | Description |
|---|---|---|---|
children | ReactNode | - | The message to display. |
...props | React.ComponentProps<typeof CommandEmpty> | - | Any other props are spread to the CommandEmpty component. |
<MicSelectorItem />
Selectable item representing a microphone.
| Prop | Type | Default | Description |
|---|---|---|---|
value | string | - | The device ID for this item. |
...props | React.ComponentProps<typeof CommandItem> | - | Any other props are spread to the CommandItem component. |
<MicSelectorLabel />
Displays a formatted microphone label with intelligent device ID parsing. Automatically extracts and styles device IDs in the format (XXXX:XXXX).
| Prop | Type | Default | Description |
|---|---|---|---|
device | MediaDeviceInfo | - | The MediaDeviceInfo object for the device. |
...props | React.ComponentProps< | - | Any other props are spread to the span element. |
Hooks
useAudioDevices()
A custom hook for managing audio input devices. This hook is used internally by the MicSelector component but can also be used independently.
import { useAudioDevices } from "@repo/elements/mic-selector";
export default function Example() {
const { devices, loading, error, hasPermission, loadDevices } =
useAudioDevices();
return (
<div>
{loading && <p>Loading devices...</p>}
{error && <p>Error: {error}</p>}
{devices.map((device) => (
<div key={device.deviceId}>{device.label}</div>
))}
{!hasPermission && (
<button onClick={loadDevices}>Grant Permission</button>
)}
</div>
);
}Return Value
| Prop | Type | Default | Description |
|---|---|---|---|
devices | MediaDeviceInfo[] | - | Array of available audio input devices. |
loading | boolean | - | Whether devices are currently being loaded. |
error | `string | null` | - |
hasPermission | boolean | - | Whether microphone permission has been granted. |
loadDevices | () => Promise<void> | - | Function to request microphone permission and load device names. |
Behavior
Permission Handling
The component implements a two-stage permission approach:
1. Without Permission: Initially loads devices without requesting permission. Device labels may show as generic names (e.g., "Microphone 1"). 2. With Permission: When the popover is opened and permission hasn't been granted, automatically requests microphone access and displays actual device names.
Device Label Parsing
The MicSelectorLabel component intelligently parses device names that include hardware IDs in the format (XXXX:XXXX). It splits the label into the device name and ID, styling the ID with muted text for better readability.
For example: "MacBook Pro Microphone (1a2b:3c4d)" becomes:
- Device name:
"MacBook Pro Microphone" - Device ID:
"(1a2b:3c4d)"(styled with muted color)
Width Synchronization
The MicSelectorTrigger uses a ResizeObserver to track its width and automatically synchronizes it with the MicSelectorContent popover width for a cohesive appearance.
Device Change Detection
The component listens for devicechange events (e.g., plugging/unplugging microphones) and automatically updates the device list in real-time.
Accessibility
- Uses semantic HTML with proper ARIA attributes via shadcn/ui components
- Full keyboard navigation support through Command component
- Screen reader friendly with proper labels and roles
- Searchable device list for quick selection
Notes
- Requires a secure context (HTTPS or localhost) for microphone access
- Browser may prompt user for microphone permission on first open
- Device labels are only fully descriptive after permission is granted
- Component handles cleanup of temporary media streams during permission requests
- Uses Radix UI's
useControllableStatefor flexible controlled/uncontrolled patterns
Model Selector
A searchable command palette for selecting AI models in your chat interface.
The ModelSelector component provides a searchable command palette interface for selecting AI models. It's built on top of the cmdk library and provides a keyboard-navigable interface with search functionality.
See scripts/model-selector.tsx for this example.
Installation
npx ai-elements@latest add model-selectorFeatures
- Searchable interface with keyboard navigation
- Fuzzy search filtering across model names
- Grouped model organization by provider
- Keyboard shortcuts support
- Empty state handling
- Customizable styling with Tailwind CSS
- Built on cmdk for excellent accessibility
- TypeScript support with proper type definitions
Props
<ModelSelector />
| Prop | Type | Default | Description |
|---|---|---|---|
...props | React.ComponentProps<typeof Dialog> | - | Any other props are spread to the underlying Dialog component. |
<ModelSelectorTrigger />
| Prop | Type | Default | Description |
|---|---|---|---|
...props | React.ComponentProps<typeof DialogTrigger> | - | Any other props are spread to the underlying DialogTrigger component. |
<ModelSelectorContent />
| Prop | Type | Default | Description |
|---|---|---|---|
title | ReactNode | - | Accessible title for the dialog (rendered in sr-only). |
...props | React.ComponentProps<typeof DialogContent> | - | Any other props are spread to the underlying DialogContent component. |
<ModelSelectorDialog />
| Prop | Type | Default | Description |
|---|---|---|---|
...props | React.ComponentProps<typeof CommandDialog> | - | Any other props are spread to the underlying CommandDialog component. |
<ModelSelectorInput />
| Prop | Type | Default | Description |
|---|---|---|---|
...props | React.ComponentProps<typeof CommandInput> | - | Any other props are spread to the underlying CommandInput component. |
<ModelSelectorList />
| Prop | Type | Default | Description |
|---|---|---|---|
...props | React.ComponentProps<typeof CommandList> | - | Any other props are spread to the underlying CommandList component. |
<ModelSelectorEmpty />
| Prop | Type | Default | Description |
|---|---|---|---|
...props | React.ComponentProps<typeof CommandEmpty> | - | Any other props are spread to the underlying CommandEmpty component. |
<ModelSelectorGroup />
| Prop | Type | Default | Description |
|---|---|---|---|
...props | React.ComponentProps<typeof CommandGroup> | - | Any other props are spread to the underlying CommandGroup component. |
<ModelSelectorItem />
| Prop | Type | Default | Description |
|---|---|---|---|
...props | React.ComponentProps<typeof CommandItem> | - | Any other props are spread to the underlying CommandItem component. |
<ModelSelectorShortcut />
| Prop | Type | Default | Description |
|---|---|---|---|
...props | React.ComponentProps<typeof CommandShortcut> | - | Any other props are spread to the underlying CommandShortcut component. |
<ModelSelectorSeparator />
| Prop | Type | Default | Description |
|---|---|---|---|
...props | React.ComponentProps<typeof CommandSeparator> | - | Any other props are spread to the underlying CommandSeparator component. |
<ModelSelectorLogo />
| Prop | Type | Default | Description |
|---|---|---|---|
provider | string | Required | The AI provider name. Supports major providers like |
...props | Omit<React.ComponentProps< | - | Any other props are spread to the underlying img element (except src and alt which are generated). |
<ModelSelectorLogoGroup />
| Prop | Type | Default | Description |
|---|---|---|---|
...props | React.ComponentProps< | - | Any other props are spread to the underlying div element. |
<ModelSelectorName />
| Prop | Type | Default | Description |
|---|---|---|---|
...props | React.ComponentProps< | - | Any other props are spread to the underlying span element. |
Node
A composable node component for React Flow-based canvases with Card-based styling.
The Node component provides a composable, Card-based node for React Flow canvases. It includes support for connection handles, structured layouts, and consistent styling using shadcn/ui components.
Installation
npx ai-elements@latest add nodeFeatures
- Built on shadcn/ui Card components for consistent styling
- Automatic handle placement (left for target, right for source)
- Composable sub-components (Header, Title, Description, Action, Content, Footer)
- Semantic structure for organizing node information
- Pre-styled sections with borders and backgrounds
- Responsive sizing with fixed small width
- Full TypeScript support with proper type definitions
- Compatible with React Flow's node system
Props
<Node />
| Prop | Type | Default | Description |
|---|---|---|---|
handles | unknown | - | Configuration for connection handles. Target renders on the left, source on the right. |
className | string | - | Additional CSS classes to apply to the node. |
...props | ComponentProps<typeof Card> | - | Any other props are spread to the underlying Card component. |
<NodeHeader />
| Prop | Type | Default | Description |
|---|---|---|---|
className | string | - | Additional CSS classes to apply to the header. |
...props | ComponentProps<typeof CardHeader> | - | Any other props are spread to the underlying CardHeader component. |
<NodeTitle />
| Prop | Type | Default | Description |
|---|---|---|---|
...props | ComponentProps<typeof CardTitle> | - | Any other props are spread to the underlying CardTitle component. |
<NodeDescription />
| Prop | Type | Default | Description |
|---|---|---|---|
...props | ComponentProps<typeof CardDescription> | - | Any other props are spread to the underlying CardDescription component. |
<NodeAction />
| Prop | Type | Default | Description |
|---|---|---|---|
...props | ComponentProps<typeof CardAction> | - | Any other props are spread to the underlying CardAction component. |
<NodeContent />
| Prop | Type | Default | Description |
|---|---|---|---|
className | string | - | Additional CSS classes to apply to the content. |
...props | ComponentProps<typeof CardContent> | - | Any other props are spread to the underlying CardContent component. |
<NodeFooter />
| Prop | Type | Default | Description |
|---|---|---|---|
className | string | - | Additional CSS classes to apply to the footer. |
...props | ComponentProps<typeof CardFooter> | - | Any other props are spread to the underlying CardFooter component. |
Open In Chat
A dropdown menu for opening queries in various AI chat platforms including ChatGPT, Claude, T3, Scira, and v0.
The OpenIn component provides a dropdown menu that allows users to open queries in different AI chat platforms with a single click.
See scripts/open-in-chat.tsx for this example.
Installation
npx ai-elements@latest add open-in-chatFeatures
- Pre-configured links to popular AI chat platforms
- Context-based query passing for cleaner API
- Customizable dropdown trigger button
- Automatic URL parameter encoding for queries
- Support for ChatGPT, Claude, T3 Chat, Scira AI, v0, and Cursor
- Branded icons for each platform
- TypeScript support with proper type definitions
- Accessible dropdown menu with keyboard navigation
- External link indicators for clarity
Supported Platforms
- ChatGPT - Opens query in OpenAI's ChatGPT with search hints
- Claude - Opens query in Anthropic's Claude AI
- T3 Chat - Opens query in T3 Chat platform
- Scira AI - Opens query in Scira's AI assistant
- v0 - Opens query in Vercel's v0 platform
- Cursor - Opens query in Cursor AI editor
Props
<OpenIn />
| Prop | Type | Default | Description |
|---|---|---|---|
query | string | - | The query text to be sent to all AI platforms. |
...props | React.ComponentProps<typeof DropdownMenu> | - | Props to spread to the underlying radix-ui DropdownMenu component. |
<OpenInTrigger />
| Prop | Type | Default | Description |
|---|---|---|---|
children | React.ReactNode | - | Custom trigger button. |
...props | React.ComponentProps<typeof DropdownMenuTrigger> | - | Props to spread to the underlying DropdownMenuTrigger component. |
<OpenInContent />
| Prop | Type | Default | Description |
|---|---|---|---|
className | string | - | Additional CSS classes to apply to the dropdown content. |
...props | React.ComponentProps<typeof DropdownMenuContent> | - | Props to spread to the underlying DropdownMenuContent component. |
<OpenInChatGPT />, <OpenInClaude />, <OpenInT3 />, <OpenInScira />, <OpenInv0 />, <OpenInCursor />
| Prop | Type | Default | Description |
|---|---|---|---|
...props | React.ComponentProps<typeof DropdownMenuItem> | - | Props to spread to the underlying DropdownMenuItem component. The query is automatically provided via context from the parent OpenIn component. |
<OpenInItem />, <OpenInLabel />, <OpenInSeparator />
Additional composable components for custom dropdown menu items, labels, and separators that follow the same props pattern as their underlying radix-ui counterparts.
Package Info
Display dependency information and version changes.
The PackageInfo component displays package dependency information including version changes and change type badges.
See scripts/package-info.tsx for this example.
Installation
npx ai-elements@latest add package-infoFeatures
- Version change display (current → new)
- Color-coded change type badges
- Dependencies list
- Description support
Change Types
| Type | Color | Use Case |
|---|---|---|
major | Red | Breaking changes |
minor | Yellow | New features |
patch | Green | Bug fixes |
added | Blue | New dependency |
removed | Gray | Removed dependency |
Props
<PackageInfo />
| Prop | Type | Default | Description |
|---|---|---|---|
name | string | Required | Package name. |
currentVersion | string | - | Current installed version. |
newVersion | string | - | New version being installed. |
changeType | unknown | - | Type of version change. |
...props | React.HTMLAttributes<HTMLDivElement> | - | Spread to the container div. |
<PackageInfoHeader />
| Prop | Type | Default | Description |
|---|---|---|---|
...props | React.HTMLAttributes<HTMLDivElement> | - | Spread to the header div. |
<PackageInfoName />
| Prop | Type | Default | Description |
|---|---|---|---|
children | React.ReactNode | - | Custom name content. Defaults to the name from context. |
...props | React.HTMLAttributes<HTMLDivElement> | - | Spread to the container div. |
<PackageInfoChangeType />
| Prop | Type | Default | Description |
|---|---|---|---|
children | React.ReactNode | - | Custom change type label. Defaults to the changeType from context. |
...props | React.HTMLAttributes<HTMLDivElement> | - | Spread to the Badge component. |
<PackageInfoVersion />
| Prop | Type | Default | Description |
|---|---|---|---|
children | React.ReactNode | - | Custom version content. Defaults to version transition display. |
...props | React.HTMLAttributes<HTMLDivElement> | - | Spread to the container div. |
<PackageInfoDescription />
| Prop | Type | Default | Description |
|---|---|---|---|
...props | React.HTMLAttributes<HTMLParagraphElement> | - | Spread to the p element. |
<PackageInfoContent />
| Prop | Type | Default | Description |
|---|---|---|---|
...props | React.HTMLAttributes<HTMLDivElement> | - | Spread to the container div. |
<PackageInfoDependencies />
| Prop | Type | Default | Description |
|---|---|---|---|
...props | React.HTMLAttributes<HTMLDivElement> | - | Spread to the container div. |
<PackageInfoDependency />
| Prop | Type | Default | Description |
|---|---|---|---|
name | string | Required | Dependency name. |
version | string | - | Dependency version. |
...props | React.HTMLAttributes<HTMLDivElement> | - | Spread to the row div. |
Panel
A styled panel component for React Flow-based canvases to position custom UI elements.
The Panel component provides a positioned container for custom UI elements on React Flow canvases. It includes modern card styling with backdrop blur and flexible positioning options.
Installation
npx ai-elements@latest add panelFeatures
- Flexible positioning (top-left, top-right, bottom-left, bottom-right, top-center, bottom-center)
- Rounded pill design with backdrop blur
- Theme-aware card background
- Flexbox layout for easy content alignment
- Subtle drop shadow for depth
- Full TypeScript support
- Compatible with React Flow's panel system
Props
<Panel />
| Prop | Type | Default | Description |
|---|---|---|---|
position | unknown | - | Position of the panel on the canvas. |
className | string | - | Additional CSS classes to apply to the panel. |
...props | ComponentProps<typeof Panel> | - | Any other props from @xyflow/react Panel component. |
"use client";
import {
FileTree,
FileTreeFile,
FileTreeFolder,
} from "@/components/ai-elements/file-tree";
const Example = () => (
<FileTree>
<FileTreeFolder name="src" path="src">
<FileTreeFile name="index.ts" path="src/index.ts" />
</FileTreeFolder>
<FileTreeFile name="package.json" path="package.json" />
</FileTree>
);
export default Example;
"use client";
import { SchemaDisplay } from "@/components/ai-elements/schema-display";
const Example = () => (
<SchemaDisplay description="List all users" method="GET" path="/api/users" />
);
export default Example;
Related skills
FAQ
Is Ai Elements safe to install?
skills.sh reports 2 of 3 security scanners passed. Review the Security Audits panel on this page before installing in production.