Chatbot Components (Remaining)
Remaining chatbot components including Checkpoint, Shimmer, Tool, Plan, Context, InlineCitation, Sources
Chatbot Components (Remaining)
Checkpoint Component
A component for marking conversation history points and restoring the chat to a previous state.
Features
- 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
Usage
"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";
const CheckpointDemo = () => {
const { messages, setMessages } = useChat();
const [checkpoints, setCheckpoints] = useState<CheckpointType[]>([]);
const createCheckpoint = (messageIndex: number) => {
const checkpoint = {
id: nanoid(),
messageIndex,
timestamp: new Date(),
messageCount: messageIndex + 1,
};
setCheckpoints([...checkpoints, checkpoint]);
};
const restoreToCheckpoint = (messageIndex: number) => {
setMessages(messages.slice(0, messageIndex + 1));
setCheckpoints(checkpoints.filter((cp) => cp.messageIndex <= messageIndex));
};
return (
<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>
);
};
Use Cases
Manual Checkpoints
<Button onClick={() => createCheckpoint(messages.length - 1)}>
Create Checkpoint
</Button>
Automatic Checkpoints
useEffect(() => {
if (messages.length > 0 && messages.length % 5 === 0) {
createCheckpoint(messages.length - 1);
}
}, [messages.length]);
Props
<Checkpoint />
| Prop | Type | Description |
|------|------|-------------|
| children | React.ReactNode | Icon and trigger components |
| ...props | React.HTMLAttributes<HTMLDivElement> | Spread to root div |
<CheckpointIcon />
| Prop | Type | Description |
|------|------|-------------|
| children | React.ReactNode | Custom icon content |
| ...props | LucideProps | Spread to BookmarkIcon |
<CheckpointTrigger />
| Prop | Type | Default |
|------|------|---------|
| children | React.ReactNode | Trigger content |
| tooltip | string | Tooltip text |
| variant | string | "ghost" |
| size | string | "sm" |
| ...props | React.ComponentProps<typeof Button> | Spread to Button |
Shimmer Component
An animated text shimmer component for creating eye-catching loading states and progressive reveal effects.
Features
- Smooth animated shimmer effect using CSS gradients and Framer Motion
- Customizable animation duration and spread
- Polymorphic component - render as any HTML element via the
asprop - Automatic spread calculation based on text length
- Theme-aware styling using CSS custom properties
- Infinite looping animation with linear easing
- Memoized for optimal performance
<Shimmer />
| Prop | Type | Default |
|------|------|---------|
| children | string | Text content |
| as | ElementType | "p" |
| className | string | Additional CSS classes |
| duration | number | Animation duration in seconds (default: 2) |
| spread | number | Spread multiplier (default: 2) |
Tool Component
A collapsible component for displaying tool invocation details in AI chatbot interfaces.
Features
- Collapsible interface for showing/hiding tool details
- Visual status indicators with icons and badges
- Support for multiple tool execution states (pending, running, completed, error)
- Formatted parameter display with JSON syntax highlighting
- Auto-opens completed tools by default
Usage
"use client";
import { useChat } from "@ai-sdk/react";
import { DefaultChatTransport, type ToolUIPart } from "ai";
import { Button } from "@/components/ui/button";
import { MessageResponse } from "@/components/ai-elements/message";
import {
Tool,
ToolContent,
ToolHeader,
ToolInput,
ToolOutput,
} from "@/components/ai-elements/tool";
type WeatherToolInput = {
location: string;
units: "celsius" | "fahrenheit";
};
type WeatherToolOutput = {
location: string;
temperature: string;
conditions: string;
humidity: string;
windSpeed: string;
lastUpdated: string;
};
type WeatherToolUIPart = ToolUIPart<{
fetch_weather_data: {
input: WeatherToolInput;
output: WeatherToolOutput;
};
}>;
const Example = () => {
const { messages, sendMessage, status } = useChat({
transport: new DefaultChatTransport({ api: "/api/weather" }),
});
const latestMessage = messages[messages.length - 1];
const weatherTool = latestMessage?.parts?.find(
(part) => part.type === "tool-fetch_weather_data"
) as WeatherToolUIPart | undefined;
return (
<div>
<Button onClick={() => sendMessage({ text: "Get weather" })} disabled={status !== "ready"}>
Get Weather
</Button>
{weatherTool && (
<Tool defaultOpen={true}>
<ToolHeader
type="tool-fetch_weather_data"
state={weatherTool.state}
/>
<ToolContent>
<ToolInput input={weatherTool.input} />
<ToolOutput
output={<MessageResponse>{formatWeatherResult(weatherTool.output)}</MessageResponse>}
errorText={weatherTool.errorText}
/>
</ToolContent>
</Tool>
)}
</div>
);
};
Backend Route
import { streamText, UIMessage, convertToModelMessages } from "ai";
import { z } from "zod";
export const maxDuration = 30;
export async function POST(req: Request) {
const { messages } = await req.json();
const result = streamText({
model: "openai/gpt-4o",
messages: await convertToModelMessages(messages),
tools: {
fetch_weather_data: {
description: "Fetch weather information",
parameters: z.object({
location: z.string().describe("The city to get weather for"),
units: z.enum(["celsius", "fahrenheit"]).default("celsius"),
}),
execute: async ({ location, units }) => {
return {
location,
temperature: `${Math.random() * 30 + 5}°`,
conditions: "Sunny",
humidity: "45%",
windSpeed: "10 km/h",
lastUpdated: new Date().toLocaleString(),
};
},
},
},
});
return result.toUIMessageStreamResponse();
}
Tool States
| State | Badge |
|-------|-------|
| input-streaming | Pending |
| input-available | Running |
| output-available | Completed |
| output-error | Error |
Props
<Tool />
| Prop | Type | Description |
|------|------|-------------|
| ...props | React.ComponentProps<typeof Collapsible> | Spread to Collapsible |
<ToolHeader />
| Prop | Type | Description |
|------|------|-------------|
| title | string | Custom title |
| type | ToolUIPart["type"] | Tool type/name |
| state | ToolUIPart["state"] | Current state |
| toolName | string | For dynamic-tool type |
| ...props | React.ComponentProps<typeof CollapsibleTrigger> | Spread to CollapsibleTrigger |
<ToolContent />
| Prop | Type | Description |
|------|------|-------------|
| ...props | React.ComponentProps<typeof CollapsibleContent> | Spread to CollapsibleContent |
<ToolInput />
| Prop | Type | Description |
|------|------|-------------|
| input | ToolUIPart["input"] | Tool input parameters |
| ...props | React.ComponentProps<"div"> | Spread to div |
<ToolOutput />
| Prop | Type | Description |
|------|------|-------------|
| output | React.ReactNode | Tool result |
| errorText | string | Error message |
| ...props | React.ComponentProps<"div"> | Spread to div |
Plan Component
A collapsible plan component for displaying AI-generated execution plans with streaming support and shimmer animations.
Features
- Collapsible content with smooth animations
- Streaming support with shimmer loading states
- Built on shadcn/ui Card and Collapsible components
Props
<Plan />
| Prop | Type | Default |
|------|------|---------|
| isStreaming | boolean | false |
| defaultOpen | boolean | - |
| ...props | React.ComponentProps<typeof Collapsible> | Spread to Collapsible |
<PlanHeader />
| Prop | Type | Description |
|------|------|-------------|
| ...props | React.ComponentProps<typeof CardHeader> | Spread to CardHeader |
<PlanTitle />
| Prop | Type | Description |
|------|------|-------------|
| children | string | Title text |
| ...props | Omit<React.ComponentProps<typeof CardTitle>, "children"> | Spread to CardTitle |
<PlanDescription />
| Prop | Type | Description |
|------|------|-------------|
| children | string | Description text |
| ...props | Omit<React.ComponentProps<typeof CardDescription>, "children"> | Spread to CardDescription |
<PlanTrigger />
| Prop | Type | Description |
|------|------|-------------|
| ...props | React.ComponentProps<typeof CollapsibleTrigger> | Spread to CollapsibleTrigger |
<PlanContent />
| Prop | Type | Description |
|------|------|-------------|
| ...props | React.ComponentProps<typeof CardContent> | Spread to CardContent |
<PlanFooter />
| Prop | Type | Description |
|------|------|-------------|
| ...props | React.ComponentProps<"div"> | Spread to div |
<PlanAction />
| Prop | Type | Description |
|------|------|-------------|
| ...props | React.ComponentProps<typeof CardAction> | Spread to CardAction |