All skills
vercel avatar

/ai-elements

@607bb65
by vercelvercel/ai-elements2.5k stars
290

Build AI chat interfaces using ai-elements components — conversations, messages, tool displays, prompt inputs, and more. Use when the user wants to build a chatbot, AI assistant UI, or any AI-powered chat interface.

Use this Skill: https://skilld.dev/gh/vercel/ai-elements/ai-elements

This session only. Nothing lands on disk.

referencestask.md

≈1.7k tokens on demand. Your agent reads this file only when SKILL.md points to it.

Task

A collapsible task list component for displaying AI workflow progress, with status indicators and optional descriptions.

The Task component provides a structured way to display task lists or workflow progress with collapsible details, status indicators, and progress tracking. It consists of a main Task container with TaskTrigger for the clickable header and TaskContent for the collapsible content area.

See scripts/task.tsx for this example.

Installation

npx ai-elements@latest add task

Usage with AI SDK

Build a mock async programming agent using experimental_generateObject.

Add the following component to your frontend:

"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 { tasksSchema } from "@/app/api/task/route";
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 handleSubmit = (taskType: string) => {
    submit({ prompt: taskType });
  };

  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 relative size-full rounded-lg border h-[600px]">
      <div className="flex flex-col h-full">
        <div className="flex gap-2 mb-6 flex-wrap">
          <Button
            onClick={() => handleSubmit("React component development")}
            disabled={isLoading}
            variant="outline"
          >
            React Development
          </Button>
        </div>

        <div className="flex-1 overflow-auto space-y-4">
          {isLoading && !object && (
            <div className="text-muted-foreground">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>
    </div>
  );
};

export default TaskDemo;

Add the following route to your backend:

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),
});

// 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: tasksSchema,
    prompt: `You are an AI assistant that generates realistic development task workflows. Generate a set of tasks that would occur during ${prompt}.

    Each task should have:
    - A descriptive title
    - Multiple task items showing the progression
    - Some items should be plain text, others should reference files
    - Use realistic file names and appropriate file types
    - Status should progress from pending to in_progress to completed

    For file items, use these icon types: 'react', 'typescript', 'javascript', 'css', 'html', 'json', 'markdown'

    Generate 3-4 tasks total, with 4-6 items each.`,
  });

  return result.toTextStreamResponse();
}

Features

  • Visual icons for pending, in-progress, completed, and error states
  • Expandable content for task descriptions and additional information
  • 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 proper TypeScript definitions
  • Keyboard navigation and screen reader support

Props

<Task />

Prop Type Default Description
defaultOpen boolean true Whether the task is open by default.
...props React.ComponentProps<typeof Collapsible> - Any other props are spread to the root Collapsible component.

<TaskTrigger />

Prop Type Default Description
title string Required The title of the task that will be displayed in the trigger.
...props React.ComponentProps<typeof CollapsibleTrigger> - Any other props are spread to the CollapsibleTrigger component.

<TaskContent />

Prop Type Default Description
...props React.ComponentProps<typeof CollapsibleContent> - Any other props are spread to the CollapsibleContent component.

<TaskItem />

Prop Type Default Description
...props React.ComponentProps< - Any other props are spread to the underlying div.

<TaskItemFile />

Prop Type Default Description
...props React.ComponentProps< - Any other props are spread to the underlying div.

Source: SKILL.md on GitHub

2 warnings16d5 checks · Risk SAFE
  • Gen Agent Trust Hub16d

    This skill provides a comprehensive library of UI components for building AI-powered chat interfaces. It includes features for rendering markdown, managing tool execution confirmations, and previewing AI-generated JSX. While the skill employs dynamic rendering and fetches assets from external sources, these operations are consistent with its intended functionality and originate from trusted or well-known service domains.

  • Socket16d

    1 alert: gptSecurity

  • Snyk16d

    Risk: LOW · No issues

  • Runlayer6mo

    5/129 files flagged

  • ZeroLeaks5mo

    Score: 93/100 · 2 sections analyzed

Signed by skilld at 607bb65. This ties the file your Agent reads to that commit on GitHub. It does not review the instructions.

Last checked against GitHub last month.

Activeupdated 7 months ago
  • React
  • ai-elements
  • shadcn-ui
  • next.js
  • chat-ui
  • ai-sdk
  • tailwind
  • components

README badge

README badge for vercel/ai-elements

Installs pre-built React components for AI chat interfaces (conversations, messages, tool displays, prompt inputs) built on shadcn/ui. Integrates with Next.js projects using the AI SDK and can be customized since components live in your codebase.

Generated from the current SKILL.md.

What are the prerequisites for using AI Elements?
You need Node.js 18 or later, a Next.js project with the AI SDK installed, and shadcn/ui configured. The CLI will automatically install shadcn/ui if you don't have it yet.
Does this work with TypeScript?
Yes. The example and component setup assume TypeScript by default, and components are added as source code to your project so you can modify them as needed.
Can I customize the components after installation?
Yes. Components are installed as source code in your project directory, not as a library, so you can directly modify Tailwind classes, props, or functionality.
What does AI Elements provide?
AI Elements is a component library built on shadcn/ui that provides pre-built UI components for AI chat interfaces, including conversations, messages, tool displays, and prompt inputs.
Does this require Vercel AI Gateway?
No, but the documentation recommends using it for easier API key management and $5 monthly usage credit for experimenting with different models.

Generated from the current SKILL.md. These answers refresh after source changes.