{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "tool",
  "type": "registry:ui",
  "title": "Tool",
  "description": "Agentic step disclosure — status chip, collapsible result. Includes Reasoning.",
  "dependencies": [
    "@base-ui/react",
    "motion",
    "lucide-react"
  ],
  "registryDependencies": [
    "https://seamui.dev/r/utils.json",
    "https://seamui.dev/r/motion.json",
    "https://seamui.dev/r/collapsible.json",
    "https://seamui.dev/r/badge.json",
    "https://seamui.dev/r/button.json",
    "https://seamui.dev/r/spinner.json",
    "https://seamui.dev/r/code-block.json"
  ],
  "files": [
    {
      "path": "registry/seam/ui/tool.tsx",
      "content": "\"use client\"\n\nimport type * as React from \"react\"\nimport { Brain, Check, ChevronDown, Wrench, X } from \"lucide-react\"\n\nimport { cn } from \"@/lib/utils\"\nimport { Badge } from \"./badge\"\nimport { Button } from \"./button\"\nimport { Spinner } from \"./spinner\"\nimport {\n  Collapsible,\n  CollapsibleContent,\n  CollapsibleTrigger,\n} from \"./collapsible\"\n\ntype ToolState = \"pending\" | \"running\" | \"done\" | \"error\"\n\n// A step row is telemetry, not a key — a quiet debossed strip carved into the\n// surface (bg-muted + shadow-well). The result sits in the well when expanded.\nfunction Tool({\n  className,\n  ...props\n}: React.ComponentProps<typeof Collapsible>) {\n  return (\n    <Collapsible\n      data-slot=\"tool\"\n      className={cn(\n        \"bg-muted/60 rounded-lg squircle border border-border/60 shadow-well\",\n        className\n      )}\n      {...props}\n    />\n  )\n}\n\nconst STATUS: Record<\n  ToolState,\n  {\n    variant: React.ComponentProps<typeof Badge>[\"variant\"]\n    label: string\n    icon: React.ReactNode\n  }\n> = {\n  pending: {\n    variant: \"muted\",\n    label: \"Pending\",\n    icon: <Spinner className=\"size-3\" />,\n  },\n  running: {\n    variant: \"secondary\",\n    label: \"Running\",\n    icon: <Spinner className=\"size-3\" />,\n  },\n  done: {\n    variant: \"secondary\",\n    label: \"Done\",\n    icon: <Check className=\"size-3\" />,\n  },\n  error: {\n    variant: \"destructive\",\n    label: \"Error\",\n    icon: <X className=\"size-3\" />,\n  },\n}\n\n// State chip. Pending/running spin; done/error resolve to an icon. Announced\n// politely so a status change is heard without interrupting.\nfunction ToolStatus({\n  status,\n  className,\n  children,\n  ...props\n}: Omit<React.ComponentProps<typeof Badge>, \"variant\"> & {\n  status: ToolState\n}) {\n  const s = STATUS[status]\n  return (\n    <Badge\n      data-slot=\"tool-status\"\n      variant={s.variant}\n      aria-live=\"polite\"\n      className={cn(\"gap-1\", className)}\n      {...props}\n    >\n      {s.icon}\n      {children ?? s.label}\n    </Badge>\n  )\n}\n\n// The disclosure trigger. Collapsible has a single trigger (no roving focus),\n// so it wears the Button component: ghost press-dim + haptic tap come from the\n// foundation, no re-rolled button base or inline motion.\nfunction ToolHeader({\n  className,\n  title,\n  status,\n  icon,\n  ...props\n}: Omit<React.ComponentProps<typeof CollapsibleTrigger>, \"title\"> & {\n  title: React.ReactNode\n  status?: ToolState\n  icon?: React.ReactNode\n}) {\n  return (\n    <CollapsibleTrigger\n      data-slot=\"tool-header\"\n      render={\n        <Button\n          variant=\"ghost\"\n          className={cn(\n            \"group/tool h-auto w-full justify-between gap-2 px-3 py-2 font-normal\",\n            className\n          )}\n        />\n      }\n      {...props}\n    >\n      <span className=\"flex min-w-0 items-center gap-2 text-sm\">\n        <span className=\"text-muted-foreground flex size-4 shrink-0 items-center justify-center [&_svg]:size-4\">\n          {icon ?? <Wrench />}\n        </span>\n        <span className=\"truncate\">{title}</span>\n      </span>\n      <span className=\"flex shrink-0 items-center gap-2\">\n        {status ? <ToolStatus status={status} /> : null}\n        <ChevronDown className=\"text-muted-foreground size-4 shrink-0 transition-transform duration-200 group-data-[panel-open]/tool:rotate-180 motion-reduce:transition-none\" />\n      </span>\n    </CollapsibleTrigger>\n  )\n}\n\nfunction ToolContent({\n  className,\n  children,\n  ...props\n}: React.ComponentProps<typeof CollapsibleContent>) {\n  return (\n    <CollapsibleContent\n      data-slot=\"tool-content\"\n      className={className}\n      {...props}\n    >\n      <div className=\"space-y-2 px-3 pb-3 pt-0.5 text-sm\">{children}</div>\n    </CollapsibleContent>\n  )\n}\n\n// Reasoning is the same disclosure shape for chain-of-thought — a Brain by\n// default and muted prose inside.\nfunction Reasoning({\n  className,\n  ...props\n}: React.ComponentProps<typeof Collapsible>) {\n  return <Tool data-slot=\"reasoning\" className={className} {...props} />\n}\n\nfunction ReasoningTrigger({\n  title = \"Reasoning\",\n  icon,\n  ...props\n}: Omit<React.ComponentProps<typeof ToolHeader>, \"title\"> & {\n  title?: React.ReactNode\n}) {\n  return <ToolHeader title={title} icon={icon ?? <Brain />} {...props} />\n}\n\nconst ReasoningContent = ToolContent\n\nexport {\n  Tool,\n  ToolHeader,\n  ToolStatus,\n  ToolContent,\n  Reasoning,\n  ReasoningTrigger,\n  ReasoningContent,\n}\n",
      "type": "registry:ui",
      "target": "components/ui/tool.tsx"
    }
  ]
}