Chatbot

Plan

A collapsible plan component for displaying AI-generated execution plans with streaming support and shimmer animations.

The Plan component provides a flexible system for displaying AI-generated execution plans with collapsible content. Perfect for showing multi-step workflows, task breakdowns, and implementation strategies with support for streaming content and loading states.

Rewrite AI Elements to SolidJS
Rewrite the AI Elements component library from React to SolidJS while maintaining compatibility with existing React-based shadcn/ui components using solid-js/compat, updating all 29 components and their test suite.
"use client";import {  Plan,  PlanAction,  PlanContent,  PlanDescription,  PlanFooter,  PlanHeader,  PlanTitle,  PlanTrigger,} from "@/components/ai-elements/elements/plan";import { Button } from "@/components/ui/button";import { FileText } from "lucide-react";const Example = () => (  <Plan defaultOpen={false}>    <PlanHeader>      <div>        <div className="mb-4 flex items-center gap-2">          <FileText className="size-4" />          <PlanTitle>Rewrite AI Elements to SolidJS</PlanTitle>        </div>        <PlanDescription>          Rewrite the AI Elements component library from React to SolidJS while          maintaining compatibility with existing React-based shadcn/ui          components using solid-js/compat, updating all 29 components and their          test suite.        </PlanDescription>      </div>      <PlanTrigger />    </PlanHeader>    <PlanContent>      <div className="space-y-4 text-sm">        <div>          <h3 className="mb-2 font-semibold">Overview</h3>          <p>            This plan outlines the migration strategy for converting the AI            Elements library from React to SolidJS, ensuring compatibility and            maintaining existing functionality.          </p>        </div>        <div>          <h3 className="mb-2 font-semibold">Key Steps</h3>          <ul className="list-inside list-disc space-y-1">            <li>Set up SolidJS project structure</li>            <li>Install solid-js/compat for React compatibility</li>            <li>Migrate components one by one</li>            <li>Update test suite for each component</li>            <li>Verify compatibility with shadcn/ui</li>          </ul>        </div>      </div>    </PlanContent>    <PlanFooter className="justify-end">      <PlanAction>        <Button size="sm">          Build <kbd className="font-mono">⌘↩</kbd>        </Button>      </PlanAction>    </PlanFooter>  </Plan>);export default Example;

Installation

npx ai-elements@latest add plan
npx shadcn@latest add @ai-elements/plan
"use client";import { Button } from "@repo/shadcn-ui/components/ui/button";import {  Card,  CardAction,  CardContent,  CardDescription,  CardFooter,  CardHeader,  CardTitle,} from "@repo/shadcn-ui/components/ui/card";import {  Collapsible,  CollapsibleContent,  CollapsibleTrigger,} from "@repo/shadcn-ui/components/ui/collapsible";import { cn } from "@repo/shadcn-ui/lib/utils";import { ChevronsUpDownIcon } from "lucide-react";import type { ComponentProps } from "react";import { createContext, useContext } from "react";import { Shimmer } from "./shimmer";type PlanContextValue = {  isStreaming: boolean;};const PlanContext = createContext<PlanContextValue | null>(null);const usePlan = () => {  const context = useContext(PlanContext);  if (!context) {    throw new Error("Plan components must be used within Plan");  }  return context;};export type PlanProps = ComponentProps<typeof Collapsible> & {  isStreaming?: boolean;};export const Plan = ({  className,  isStreaming = false,  children,  ...props}: PlanProps) => (  <PlanContext.Provider value={{ isStreaming }}>    <Collapsible asChild data-slot="plan" {...props}>      <Card className={cn("shadow-none", className)}>{children}</Card>    </Collapsible>  </PlanContext.Provider>);export type PlanHeaderProps = ComponentProps<typeof CardHeader>;export const PlanHeader = ({ className, ...props }: PlanHeaderProps) => (  <CardHeader    className={cn("flex items-start justify-between", className)}    data-slot="plan-header"    {...props}  />);export type PlanTitleProps = Omit<  ComponentProps<typeof CardTitle>,  "children"> & {  children: string;};export const PlanTitle = ({ children, ...props }: PlanTitleProps) => {  const { isStreaming } = usePlan();  return (    <CardTitle data-slot="plan-title" {...props}>      {isStreaming ? <Shimmer>{children}</Shimmer> : children}    </CardTitle>  );};export type PlanDescriptionProps = Omit<  ComponentProps<typeof CardDescription>,  "children"> & {  children: string;};export const PlanDescription = ({  className,  children,  ...props}: PlanDescriptionProps) => {  const { isStreaming } = usePlan();  return (    <CardDescription      className={cn("text-balance", className)}      data-slot="plan-description"      {...props}    >      {isStreaming ? <Shimmer>{children}</Shimmer> : children}    </CardDescription>  );};export type PlanActionProps = ComponentProps<typeof CardAction>;export const PlanAction = (props: PlanActionProps) => (  <CardAction data-slot="plan-action" {...props} />);export type PlanContentProps = ComponentProps<typeof CardContent>;export const PlanContent = (props: PlanContentProps) => (  <CollapsibleContent asChild>    <CardContent data-slot="plan-content" {...props} />  </CollapsibleContent>);export type PlanFooterProps = ComponentProps<"div">;export const PlanFooter = (props: PlanFooterProps) => (  <CardFooter data-slot="plan-footer" {...props} />);export type PlanTriggerProps = ComponentProps<typeof CollapsibleTrigger>;export const PlanTrigger = ({ className, ...props }: PlanTriggerProps) => (  <CollapsibleTrigger asChild>    <Button      className={cn("size-8", className)}      data-slot="plan-trigger"      size="icon"      variant="ghost"      {...props}    >      <ChevronsUpDownIcon className="size-4" />      <span className="sr-only">Toggle plan</span>    </Button>  </CollapsibleTrigger>);

Usage

import {
  Plan,
  PlanAction,
  PlanContent,
  PlanDescription,
  PlanFooter,
  PlanHeader,
  PlanTitle,
  PlanTrigger,
} from '@/components/ai-elements/plan';
<Plan defaultOpen={false}>
  <PlanHeader>
    <div>
      <PlanTitle>Implement new feature</PlanTitle>
      <PlanDescription>
        Add authentication system with JWT tokens and refresh logic.
      </PlanDescription>
    </div>
    <PlanTrigger />
  </PlanHeader>
  <PlanContent>
    <div className="space-y-4 text-sm">
      <div>
        <h3 className="mb-2 font-semibold">Overview</h3>
        <p>This plan outlines the implementation strategy...</p>
      </div>
    </div>
  </PlanContent>
  <PlanFooter>
    <Button>Execute Plan</Button>
  </PlanFooter>
</Plan>

Features

  • Collapsible content with smooth animations
  • Streaming support with shimmer loading states
  • Built on shadcn/ui Card and Collapsible components
  • TypeScript support with comprehensive type definitions
  • Customizable styling with Tailwind CSS
  • Responsive design with mobile-friendly interactions
  • Keyboard navigation and accessibility support
  • Theme-aware with automatic dark mode support
  • Context-based state management for streaming

Props

<Plan />

Prop

Type

<PlanHeader />

Prop

Type

<PlanTitle />

Prop

Type

<PlanDescription />

Prop

Type

<PlanTrigger />

Prop

Type

<PlanContent />

Prop

Type

<PlanFooter />

Prop

Type

<PlanAction />

Prop

Type