{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "tool-call",
  "title": "Tool Call",
  "description": "Queued, running, successful, and failed tool activity with a disclosure for input and output.",
  "dependencies": [
    "class-variance-authority",
    "lucide-react"
  ],
  "registryDependencies": [
    "collapsible",
    "https://uaiblocks.dev/r/uai-theme.json",
    "https://uaiblocks.dev/r/uai-utils.json"
  ],
  "files": [
    {
      "path": "src/registry/uai/components/tool-call.tsx",
      "content": "\"use client\";\n\nimport { cva } from \"class-variance-authority\";\nimport {\n  Check,\n  ChevronDown,\n  CircleAlert,\n  CircleDashed,\n  LoaderCircle,\n  type LucideIcon,\n} from \"lucide-react\";\nimport {\n  type ComponentProps,\n  createContext,\n  type ReactNode,\n  useContext,\n  useId,\n  useState,\n} from \"react\";\nimport { Collapsible, CollapsibleTrigger } from \"@/components/ui/collapsible\";\nimport { cn } from \"@/lib/uai-utils\";\n\nexport const TOOL_CALL_VARIANTS = [\"card\", \"inline\", \"compact\"] as const;\nexport const TOOL_CALL_STATUSES = [\"queued\", \"running\", \"success\", \"error\"] as const;\nexport type ToolCallVariant = (typeof TOOL_CALL_VARIANTS)[number];\nexport type ToolCallStatus = (typeof TOOL_CALL_STATUSES)[number];\nexport type ToolCallProps = ComponentProps<\"div\"> & {\n  variant?: ToolCallVariant;\n  status?: ToolCallStatus;\n  open?: boolean;\n  defaultOpen?: boolean;\n  onOpenChange?: (open: boolean) => void;\n};\n\ntype ToolCallContextValue = {\n  id: string;\n  variant: ToolCallVariant;\n  status: ToolCallStatus;\n  open: boolean;\n};\n\nconst ToolCallContext = createContext<ToolCallContextValue | null>(null);\n\nfunction useToolCall(part: string) {\n  const context = useContext(ToolCallContext);\n  if (!context) throw new Error(`${part} must be used within ToolCall`);\n  return context;\n}\n\nconst dangerText = \"text-destructive-ink\";\nconst statusDetails: Record<\n  ToolCallStatus,\n  { label: string; icon: LucideIcon; color: string; tint: string }\n> = {\n  queued: {\n    label: \"Queued\",\n    icon: CircleDashed,\n    color: \"text-subtle-foreground\",\n    tint: \"bg-transparent shadow-[inset_0_0_0_1px_var(--border)]\",\n  },\n  running: {\n    label: \"Running\",\n    icon: LoaderCircle,\n    color: \"text-foreground\",\n    tint: \"bg-muted\",\n  },\n  success: {\n    label: \"Succeeded\",\n    icon: Check,\n    color: \"text-success-ink\",\n    tint: \"bg-success/14\",\n  },\n  error: {\n    label: \"Failed\",\n    icon: CircleAlert,\n    color: dangerText,\n    tint: \"bg-destructive/14\",\n  },\n};\n\nconst toolCallVariants = cva(\"min-w-0 overflow-hidden text-[13px]/[18px] text-foreground\", {\n  variants: {\n    variant: {\n      card: \"rounded-[14px] border bg-card\",\n      inline: \"rounded-[14px] border-0 bg-transparent\",\n      compact: \"rounded-xl border bg-card\",\n    },\n    error: { true: \"\", false: \"\" },\n  },\n  compoundVariants: [\n    {\n      variant: [\"card\", \"compact\"],\n      error: true,\n      className: \"border-[color-mix(in_oklab,var(--destructive)_45%,var(--border))]\",\n    },\n  ],\n});\n\nexport function ToolCall({\n  variant = \"card\",\n  status = \"queued\",\n  open,\n  defaultOpen = false,\n  onOpenChange,\n  className,\n  children,\n  ...props\n}: ToolCallProps) {\n  const id = useId();\n  const [internal, setInternal] = useState(defaultOpen);\n  const visible = open ?? internal;\n  return (\n    <ToolCallContext.Provider value={{ id, variant, status, open: visible }}>\n      <Collapsible\n        data-slot=\"tool-call\"\n        className={cn(toolCallVariants({ variant, error: status === \"error\" }), className)}\n        {...props}\n        open={visible}\n        onOpenChange={(next) => {\n          if (open === undefined) setInternal(next);\n          onOpenChange?.(next);\n        }}\n        aria-busy={status === \"running\" || undefined}\n        data-variant={variant}\n        data-status={status}\n      >\n        {children}\n      </Collapsible>\n    </ToolCallContext.Provider>\n  );\n}\n\nexport function ToolCallHeader({ className, ...props }: ComponentProps<\"div\">) {\n  const context = useToolCall(\"ToolCallHeader\");\n  return (\n    <div\n      data-slot=\"tool-call-header\"\n      className={cn(\n        \"flex min-w-0 items-center gap-2\",\n        context.variant === \"inline\" ? \"pr-1\" : context.variant === \"compact\" ? \"pr-2\" : \"pr-3\",\n        className,\n      )}\n      {...props}\n    />\n  );\n}\n\nfunction StatusIcon({ status, size }: { status: ToolCallStatus; size: number }) {\n  const { icon: Icon, color } = statusDetails[status];\n  return (\n    <Icon\n      key={status}\n      size={size}\n      strokeWidth={2}\n      aria-hidden=\"true\"\n      className={cn(\n        \"flex-none\",\n        color,\n        status === \"running\" && \"motion-safe:animate-spin\",\n        (status === \"success\" || status === \"error\") &&\n          \"animate-in duration-200 ease-out-quint fade-in-0 zoom-in-50 motion-reduce:animate-none\",\n      )}\n    />\n  );\n}\n\nexport function ToolCallTrigger({ children, className, ...props }: ComponentProps<\"button\">) {\n  const context = useToolCall(\"ToolCallTrigger\");\n  const compact = context.variant === \"compact\";\n  const inline = context.variant === \"inline\";\n  return (\n    <CollapsibleTrigger\n      data-slot=\"tool-call-trigger\"\n      type=\"button\"\n      className={cn(\n        \"group/tool-call-trigger flex min-w-0 flex-auto cursor-pointer items-center gap-2 border-0 bg-transparent text-left font-[inherit] text-inherit outline-none transition-[background-color] duration-120 ease-out hover:bg-accent/50 focus-visible:outline-2 focus-visible:outline-solid focus-visible:-outline-offset-2 focus-visible:outline-ring motion-reduce:transition-none\",\n        compact ? \"min-h-[34px]\" : \"min-h-11\",\n        inline ? \"rounded-[10px] px-1.5\" : compact ? \"rounded-none px-2\" : \"rounded-none px-3\",\n        className,\n      )}\n      {...props}\n      aria-controls={`${context.id}-content`}\n    >\n      <span\n        className={cn(\n          \"grid flex-none place-items-center transition-[background-color] duration-200 ease-out\",\n          compact ? \"size-5 rounded-[6px]\" : \"size-6 rounded-lg\",\n          statusDetails[context.status].tint,\n        )}\n      >\n        <StatusIcon status={context.status} size={compact ? 12 : 13} />\n      </span>\n      <span className=\"flex min-w-0 flex-1 items-baseline gap-2\">{children}</span>\n      <ChevronDown\n        size={14}\n        aria-hidden=\"true\"\n        className={cn(\n          \"size-3.5\",\n          \"flex-none text-subtle-foreground [transition:rotate_180ms_cubic-bezier(0.23,1,0.32,1),color_120ms_ease-out] group-hover/tool-call-trigger:text-foreground group-aria-expanded/tool-call-trigger:rotate-180 motion-reduce:transition-none\",\n        )}\n      />\n    </CollapsibleTrigger>\n  );\n}\n\nexport function ToolCallName({ className, ...props }: ComponentProps<\"span\">) {\n  useToolCall(\"ToolCallName\");\n  return (\n    <span\n      data-slot=\"tool-call-name\"\n      className={cn(\"flex-none font-mono text-[12px] font-medium tracking-[-0.01em]\", className)}\n      {...props}\n    />\n  );\n}\n\nexport function ToolCallSummary({ className, ...props }: ComponentProps<\"span\">) {\n  useToolCall(\"ToolCallSummary\");\n  return (\n    <span\n      data-slot=\"tool-call-summary\"\n      className={cn(\"min-w-0 truncate text-[12.5px] text-muted-foreground\", className)}\n      {...props}\n    />\n  );\n}\n\nexport function ToolCallStatus({ children, className, ...props }: ComponentProps<\"span\">) {\n  const context = useToolCall(\"ToolCallStatus\");\n  const details = statusDetails[context.status];\n  const settled = context.status === \"success\" || context.status === \"error\";\n  return (\n    <span\n      data-slot=\"tool-call-status\"\n      role=\"status\"\n      className={cn(\n        \"flex-none rounded-full py-0.5 text-[11.5px]/4 font-medium whitespace-nowrap tabular-nums\",\n        settled ? cn(\"px-2\", details.tint, details.color) : \"px-0\",\n        context.status === \"queued\" && \"text-subtle-foreground\",\n        context.status === \"running\" && \"shimmer-text\",\n        className,\n      )}\n      {...props}\n    >\n      {children ?? details.label}\n    </span>\n  );\n}\n\nexport function ToolCallContent({ className, ...props }: ComponentProps<\"div\">) {\n  const context = useToolCall(\"ToolCallContent\");\n  const inline = context.variant === \"inline\";\n  return (\n    <div\n      inert={!context.open}\n      className={cn(\n        \"grid transition-[grid-template-rows,opacity] duration-300 ease-out-quint motion-reduce:transition-none\",\n        context.open ? \"grid-rows-[1fr] opacity-100\" : \"grid-rows-[0fr] opacity-0\",\n      )}\n    >\n      <div className=\"min-h-0 overflow-hidden\">\n        {/* Always mounted: the outer grid animates the height, so the region never unmounts. */}\n        <div\n          data-slot=\"tool-call-content\"\n          data-state={context.open ? \"open\" : \"closed\"}\n          className={cn(\n            \"grid gap-2.5\",\n            inline\n              ? \"border-t-0 pt-1.5 pr-0 pb-1 pl-[38px]\"\n              : cn(\"border-t\", context.variant === \"compact\" ? \"p-2\" : \"p-3\"),\n            className,\n          )}\n          {...props}\n          id={`${context.id}-content`}\n        />\n      </div>\n    </div>\n  );\n}\n\nexport type ToolCallPayloadProps = ComponentProps<\"div\"> & {\n  /** Heading shown above the payload. */\n  label?: ReactNode;\n};\n\nfunction Payload({\n  part,\n  slot,\n  defaultLabel,\n  label,\n  className,\n  children,\n  ...props\n}: ToolCallPayloadProps & { part: string; slot: string; defaultLabel: string }) {\n  const context = useToolCall(part);\n  const labelId = `${context.id}-${defaultLabel.toLowerCase()}`;\n  return (\n    // biome-ignore lint/a11y/useSemanticElements: a labelled group keeps the payload heading lightweight inside chat logs.\n    <div\n      data-slot={slot}\n      role=\"group\"\n      aria-labelledby={labelId}\n      className={cn(\"grid gap-1\", className)}\n      {...props}\n    >\n      <span id={labelId} className=\"text-[11.5px]/4 text-subtle-foreground\">\n        {label ?? defaultLabel}\n      </span>\n      <pre\n        className={cn(\n          \"m-0 max-h-[220px] overflow-auto px-2.5 py-2 font-mono text-[11.5px]/[18px] whitespace-pre-wrap text-[color-mix(in_oklab,var(--foreground)_88%,var(--muted-foreground))] wrap-anywhere\",\n          context.variant === \"compact\" ? \"rounded-lg\" : \"rounded-[10px]\",\n          context.variant === \"inline\" ? \"bg-muted\" : \"bg-background\",\n        )}\n      >\n        {children}\n      </pre>\n    </div>\n  );\n}\n\nexport function ToolCallInput(props: ToolCallPayloadProps) {\n  return <Payload {...props} part=\"ToolCallInput\" slot=\"tool-call-input\" defaultLabel=\"Input\" />;\n}\n\nexport function ToolCallOutput(props: ToolCallPayloadProps) {\n  const context = useToolCall(\"ToolCallOutput\");\n  if (context.status === \"queued\" || context.status === \"error\") return null;\n  return <Payload {...props} part=\"ToolCallOutput\" slot=\"tool-call-output\" defaultLabel=\"Output\" />;\n}\n\nexport function ToolCallError({ children, className, ...props }: ComponentProps<\"p\">) {\n  const context = useToolCall(\"ToolCallError\");\n  if (context.status !== \"error\") return null;\n  return (\n    <p\n      data-slot=\"tool-call-error\"\n      className={cn(\n        \"m-0 flex items-start gap-2 rounded-[10px] bg-destructive/10 px-2.5 py-2 text-[12.5px]\",\n        dangerText,\n        className,\n      )}\n      {...props}\n    >\n      <CircleAlert size={14} aria-hidden=\"true\" className=\"mt-0.5 flex-none size-3.5\" />\n      <span>{children ?? \"The tool returned an error.\"}</span>\n    </p>\n  );\n}\n",
      "type": "registry:ui",
      "target": "@ui/uai/tool-call.tsx"
    }
  ],
  "categories": [
    "ai",
    "agents"
  ],
  "type": "registry:ui"
}