{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "elements-tool-timeline",
  "type": "registry:component",
  "title": "Tool timeline",
  "description": "A whole working session summarized as verbs, targets, and file stats.",
  "registryDependencies": [
    "https://r.assistant-ui.com/elements-surfaces.json",
    "https://r.assistant-ui.com/elements-range.json",
    "collapsible"
  ],
  "dependencies": [
    "lucide-react"
  ],
  "files": [
    {
      "type": "registry:component",
      "path": "components/assistant-ui/elements/tool-timeline.tsx",
      "sourcePath": "packages/ui/src/components/react/assistant-ui/elements/tool-timeline.tsx",
      "content": "\"use client\";\n\nimport { ChevronRightIcon, type LucideIcon } from \"lucide-react\";\nimport {\n  Collapsible,\n  CollapsibleContent,\n  CollapsibleTrigger,\n} from \"@/components/ui/collapsible\";\nimport { cn } from \"@/lib/utils\";\nimport { collapsePanel, ShimmerLabel, SwapLabel } from \"./surfaces\";\nimport { take } from \"../utils/range\";\n\nexport interface TimelineStep {\n  verb: string;\n  chip: string;\n  icon: LucideIcon;\n}\n\nexport interface TimelineStat {\n  file: string;\n  added?: number;\n  removed?: number;\n}\n\nexport interface ToolTimelineProps {\n  steps: readonly TimelineStep[];\n  visibleSteps: number;\n  streaming: boolean;\n  open: boolean;\n  onOpenChange: (open: boolean) => void;\n  restingLabel: string;\n  activeLabel: string;\n  stats: TimelineStat[];\n  className?: string;\n}\n\nexport function ToolTimeline({\n  steps,\n  visibleSteps,\n  streaming,\n  open,\n  onOpenChange,\n  restingLabel,\n  activeLabel,\n  stats,\n  className,\n}: ToolTimelineProps) {\n  return (\n    <Collapsible\n      data-slot=\"tool-timeline\"\n      open={open}\n      onOpenChange={onOpenChange}\n      className={cn(\"w-full max-w-sm\", className)}\n    >\n      <CollapsibleTrigger className=\"group/trigger text-foreground/55 hover:text-foreground/90 flex items-center gap-1.5 rounded-md py-1 text-[13.5px] transition-colors outline-none\">\n        <ChevronRightIcon className=\"size-3.5 shrink-0 opacity-60 transition-transform duration-200 ease-[cubic-bezier(0.32,0.72,0,1)] group-data-open/trigger:rotate-90 group-data-panel-open/trigger:rotate-90 motion-reduce:transition-none\" />\n        <SwapLabel\n          active={streaming ? 0 : 1}\n          className=\"text-start tabular-nums\"\n        >\n          <ShimmerLabel\n            active={streaming}\n            className=\"relative inline-block leading-none\"\n          >\n            {activeLabel}\n          </ShimmerLabel>\n          <>{restingLabel}</>\n        </SwapLabel>\n      </CollapsibleTrigger>\n      <CollapsibleContent className={cn(collapsePanel, \"outline-none\")}>\n        <div className=\"flex flex-col gap-2.5 ps-4 pt-2.5\">\n          {take(steps, visibleSteps).map((step, index, shown) => {\n            const Icon = step.icon;\n            const active = streaming && index === shown.length - 1;\n\n            return (\n              <div\n                key={step.chip}\n                className=\"fade-in slide-in-from-bottom-1 animate-in fill-mode-both text-foreground/55 flex items-center gap-2 text-[13.5px] duration-300\"\n              >\n                <Icon className=\"text-foreground/35 size-3.5 shrink-0\" />\n                <ShimmerLabel\n                  active={active}\n                  className=\"relative inline-block leading-none\"\n                >\n                  {step.verb}\n                </ShimmerLabel>\n                <span className=\"bg-foreground/[0.06] text-foreground/70 rounded-md px-1.5 py-0.5 font-mono text-[11px]\">\n                  {step.chip}\n                </span>\n              </div>\n            );\n          })}\n          {stats.length > 0 && (\n            <div className=\"flex flex-wrap gap-1.5 pt-1\">\n              {stats.map((stat) => (\n                <span\n                  key={stat.file}\n                  className=\"bg-foreground/[0.06] text-foreground/70 inline-flex items-center gap-1 rounded-md px-1.5 py-0.5 font-mono text-[11px]\"\n                >\n                  <span>{stat.file}</span>\n                  {stat.added !== undefined && (\n                    <span className=\"text-emerald-600 dark:text-emerald-400\">\n                      +{stat.added}\n                    </span>\n                  )}\n                  {stat.removed !== undefined && (\n                    <span className=\"text-red-600 dark:text-red-400\">\n                      −{stat.removed}\n                    </span>\n                  )}\n                </span>\n              ))}\n            </div>\n          )}\n        </div>\n      </CollapsibleContent>\n    </Collapsible>\n  );\n}\n"
    }
  ]
}