Chatbot Components (Advanced)
Advanced chatbot components including ChainOfThought, Task, Confirmation, Queue
Chatbot Components (Advanced)
ChainOfThought Component
A collapsible component that visualizes AI reasoning steps with support for search results, images, and step-by-step progress indicators.
Features
- 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
- Smooth fade and slide animations for content transitions
- Composable architecture for flexible customization
<ChainOfThought />
| Prop | Type | Default |
|------|------|---------|
| open | boolean | Controlled open state |
| defaultOpen | boolean | false |
| onOpenChange | (open: boolean) => void | Callback when open changes |
| ...props | React.ComponentProps<"div"> | Spread to root div |
<ChainOfThoughtHeader />
| Prop | Type | Default |
|------|------|---------|
| children | React.ReactNode | "Chain of Thought" |
| ...props | React.ComponentProps<typeof CollapsibleTrigger> | Spread to CollapsibleTrigger |
<ChainOfThoughtStep />
| Prop | Type | Default |
|------|------|---------|
| icon | LucideIcon | DotIcon |
| label | string | Step label text |
| description | string | Optional description |
| status | "complete" \| "active" \| "pending" | "complete" |
| ...props | React.ComponentProps<"div"> | Spread to root div |
<ChainOfThoughtSearchResults />
| Prop | Type | Description |
|------|------|-------------|
| ...props | React.ComponentProps<"div"> | Spread to container div |
<ChainOfThoughtSearchResult />
| Prop | Type | Description |
|------|------|-------------|
| ...props | React.ComponentProps<typeof Badge> | Spread to Badge |
<ChainOfThoughtContent />
| Prop | Type | Description |
|------|------|-------------|
| ...props | React.ComponentProps<typeof CollapsibleContent> | Spread to CollapsibleContent |
<ChainOfThoughtImage />
| Prop | Type | Description |
|------|------|-------------|
| caption | string | Optional caption below image |
| ...props | React.ComponentProps<"div"> | Spread to container div |
Task Component
A collapsible task list component for displaying AI workflow progress with status indicators and optional descriptions.
Features
- Visual icons for pending, in-progress, completed, and error states
- Expandable content for task descriptions
- Built-in progress counter showing completed vs total tasks
- Optional progressive reveal of tasks with customizable timing
- Support for custom content within task items
- Full type safety with TypeScript definitions
Usage
"use client";
import { experimental_useObject as useObject } from "@ai-sdk/react";
import {
Task,
TaskItem,
TaskItemFile,
TaskTrigger,
TaskContent,
} from "@/components/ai-elements/task";
import { Button } from "@/components/ui/button";
import {
SiReact,
SiTypescript,
SiJavascript,
SiCss,
SiHtml5,
SiJson,
SiMarkdown,
} from "@icons-pack/react-simple-icons";
const iconMap = {
react: { component: SiReact, color: "#149ECA" },
typescript: { component: SiTypescript, color: "#3178C6" },
javascript: { component: SiJavascript, color: "#F7DF1E" },
css: { component: SiCss, color: "#1572B6" },
html: { component: SiHtml5, color: "#E34F26" },
json: { component: SiJson, color: "#000000" },
markdown: { component: SiMarkdown, color: "#000000" },
};
const TaskDemo = () => {
const { object, submit, isLoading } = useObject({
api: "/api/agent",
schema: tasksSchema,
});
const renderTaskItem = (item: any, index: number) => {
if (item?.type === "file" && item.file) {
const iconInfo = iconMap[item.file.icon as keyof typeof iconMap];
if (iconInfo) {
const IconComponent = iconInfo.component;
return (
<span className="inline-flex items-center gap-1" key={index}>
{item.text}
<TaskItemFile>
<IconComponent color={item.file.color || iconInfo.color} className="size-4" />
<span>{item.file.name}</span>
</TaskItemFile>
</span>
);
}
}
return item?.text || "";
};
return (
<div className="max-w-4xl mx-auto p-6 rounded-lg border h-[600px]">
<div className="flex gap-2 mb-6 flex-wrap">
<Button onClick={() => submit({ prompt: "React component development" })} disabled={isLoading}>
React Development
</Button>
</div>
<div className="flex-1 overflow-auto space-y-4">
{isLoading && !object && <div>Generating tasks...</div>}
{object?.tasks?.map((task: any, taskIndex: number) => (
<Task key={taskIndex} defaultOpen={taskIndex === 0}>
<TaskTrigger title={task.title || "Loading..."} />
<TaskContent>
{task.items?.map((item: any, itemIndex: number) => (
<TaskItem key={itemIndex}>
{renderTaskItem(item, itemIndex)}
</TaskItem>
))}
</TaskContent>
</Task>
))}
</div>
</div>
);
};
Backend Route
import { streamObject } from "ai";
import { z } from "zod";
export const taskItemSchema = z.object({
type: z.enum(["text", "file"]),
text: z.string(),
file: z.object({
name: z.string(),
icon: z.string(),
color: z.string().optional(),
}).optional(),
});
export const taskSchema = z.object({
title: z.string(),
items: z.array(taskItemSchema),
status: z.enum(["pending", "in_progress", "completed"]),
});
export const tasksSchema = z.object({
tasks: z.array(taskSchema),
});
export const maxDuration = 30;
export async function POST(req: Request) {
const { prompt } = await req.json();
const result = streamObject({
model: "openai/gpt-4o",
schema: tasksSchema,
prompt: `You are an AI assistant that generates realistic development task workflows.`,
});
return result.toTextStreamResponse();
}
<Task />
| Prop | Type | Default |
|------|------|---------|
| defaultOpen | boolean | true |
| ...props | React.ComponentProps<typeof Collapsible> | Spread to Collapsible |
<TaskTrigger />
| Prop | Type | Description |
|------|------|-------------|
| title | string | Task title (required) |
| ...props | React.ComponentProps<typeof CollapsibleTrigger> | Spread to CollapsibleTrigger |
<TaskContent />
| Prop | Type | Description |
|------|------|-------------|
| ...props | React.ComponentProps<typeof CollapsibleContent> | Spread to CollapsibleContent |
<TaskItem />
| Prop | Type | Description |
|------|------|-------------|
| ...props | React.ComponentProps<"div"> | Spread to div |
<TaskItemFile />
| Prop | Type | Description |
|------|------|-------------|
| ...props | React.ComponentProps<"div"> | Spread to div |
Confirmation Component
An alert-based component for managing tool execution approval workflows with request, accept, and reject states.
Features
- Request, accept, and reject states for tool approval
- Visual feedback for approval outcomes
- Customizable action buttons
- Integration with AI SDK tool approval system
Usage
"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,
ConfirmationTitle,
ConfirmationRequest,
ConfirmationAccepted,
ConfirmationRejected,
ConfirmationActions,
ConfirmationAction,
} from "@/components/ai-elements/confirmation";
type DeleteFileToolUIPart = ToolUIPart<{
delete_file: {
input: { filePath: string; confirm: boolean };
output: { success: boolean; message: string };
};
}>;
const Example = () => {
const { messages, sendMessage, addToolApprovalResponse } = useChat({
transport: new DefaultChatTransport({ api: "/api/chat" }),
});
const latestMessage = messages[messages.length - 1];
const deleteTool = latestMessage?.parts?.find(
(part) => part.type === "tool-delete_file"
) as DeleteFileToolUIPart | undefined;
return (
<div>
<Button onClick={() => sendMessage({ text: "Delete the file" })}>
Delete Example File
</Button>
{deleteTool?.approval && (
<Confirmation approval={deleteTool.approval} state={deleteTool.state}>
<ConfirmationRequest>
This tool wants to delete: <code>{deleteTool.input?.filePath}</code>
</ConfirmationRequest>
<ConfirmationAccepted>
<CheckIcon className="size-4" />
<span>Approved</span>
</ConfirmationAccepted>
<ConfirmationRejected>
<XIcon className="size-4" />
<span>Rejected</span>
</ConfirmationRejected>
<ConfirmationActions>
<ConfirmationAction
variant="outline"
onClick={() =>
addToolApprovalResponse({
id: deleteTool.approval!.id,
approved: false,
})
}
>
Reject
</ConfirmationAction>
<ConfirmationAction
onClick={() =>
addToolApprovalResponse({
id: deleteTool.approval!.id,
approved: true,
})
}
>
Approve
</ConfirmationAction>
</ConfirmationActions>
</Confirmation>
)}
</div>
);
};
Confirmation Components
| Component | Purpose |
|-----------|---------|
| Confirmation | Main wrapper with approval and state props |
| ConfirmationTitle | Title for the confirmation |
| ConfirmationRequest | Request description |
| ConfirmationAccepted | Accepted state display |
| ConfirmationRejected | Rejected state display |
| ConfirmationActions | Action buttons container |
| ConfirmationAction | Individual action button |
Queue Component
A comprehensive queue component system for displaying message lists, todos, and collapsible task sections.
Features
- Flexible component system with composable parts
- Collapsible sections with smooth animations
- Support for completed/pending state indicators
- Built-in scroll area for long lists
- Attachment display with images and file indicators
- Hover-revealed action buttons for queue items
- Responsive design with mobile-friendly interactions
<Queue />
| Prop | Type | Description |
|------|------|-------------|
| ...props | React.ComponentProps<"div"> | Spread to root div |
<QueueSection />
| Prop | Type | Default |
|------|------|---------|
| defaultOpen | boolean | true |
| ...props | React.ComponentProps<typeof Collapsible> | Spread to Collapsible |
<QueueSectionTrigger />
| Prop | Type | Description |
|------|------|-------------|
| ...props | React.ComponentProps<"button"> | Spread to button |
<QueueSectionLabel />
| Prop | Type | Description |
|------|------|-------------|
| label | string | Label text |
| count | number | Count to display before label |
| icon | React.ReactNode | Optional icon before count |
| ...props | React.ComponentProps<"span"> | Spread to span |
<QueueSectionContent />
| Prop | Type | Description |
|------|------|-------------|
| ...props | React.ComponentProps<typeof CollapsibleContent> | Spread to CollapsibleContent |