ai-sdk-elements/Components

Chatbot Components (Advanced)

Advanced chatbot components including ChainOfThought, Task, Confirmation, Queue

chain-of-thoughttaskconfirmationqueue

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 |