{"$schema":"https://ui.shadcn.com/schema/registry-item.json","name":"reasoning-steps","type":"registry:ui","title":"Reasoning Steps","description":"A multi-step reasoning trace — each step with its own status and timer, so a long think reads as progress, not a hang.","author":"Scrim UI (https://scrimui.dev)","categories":["reasoning"],"docs":"https://scrimui.dev/components/reasoning-steps","dependencies":[],"registryDependencies":[],"files":[{"path":"src/showcase/reasoning-steps/reasoning-steps.tsx","content":"\"use client\";\n\nimport * as React from \"react\";\n\n/* ------------------------------------------------------------------ */\n/* Types                                                               */\n/* ------------------------------------------------------------------ */\n\nexport type ReasoningStepsProps = {\n  /** Each step's short label, in order. */\n  steps: string[];\n  /** Index of the step currently running — earlier steps render as done, later ones as pending. */\n  activeStep?: number;\n  /** Time spent on the active step, shown next to it (e.g. \"3.2s\"). */\n  elapsed?: string;\n  defaultExpanded?: boolean;\n  title?: string;\n  className?: string;\n};\n\n/* ------------------------------------------------------------------ */\n/* Icons                                                               */\n/* ------------------------------------------------------------------ */\n\nfunction ChevronIcon({ open }: { open: boolean }) {\n  return (\n    <svg\n      viewBox=\"0 0 24 24\"\n      fill=\"none\"\n      stroke=\"currentColor\"\n      strokeWidth=\"2\"\n      strokeLinecap=\"round\"\n      strokeLinejoin=\"round\"\n      width=\"14\"\n      height=\"14\"\n      className={`transition-transform ${open ? \"rotate-180\" : \"\"}`}\n    >\n      <path d=\"m6 9 6 6 6-6\" />\n    </svg>\n  );\n}\n\nfunction CheckIcon() {\n  return (\n    <svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2.5\" strokeLinecap=\"round\" strokeLinejoin=\"round\" width=\"13\" height=\"13\">\n      <path d=\"M20 6 9 17l-5-5\" />\n    </svg>\n  );\n}\n\n/* ------------------------------------------------------------------ */\n/* ReasoningSteps                                                      */\n/* ------------------------------------------------------------------ */\n\nexport function ReasoningSteps({\n  steps,\n  activeStep = -1,\n  elapsed,\n  defaultExpanded = true,\n  title = \"Reasoning\",\n  className = \"\",\n}: ReasoningStepsProps) {\n  const [open, setOpen] = React.useState(defaultExpanded);\n  const doneCount = steps.filter((_, i) => i < activeStep).length;\n\n  return (\n    <div className={`overflow-hidden rounded-xl border border-zinc-200 dark:border-zinc-800 ${className}`}>\n      <button\n        type=\"button\"\n        onClick={() => setOpen((o) => !o)}\n        className=\"flex w-full items-center gap-2 bg-zinc-50 px-3 py-2.5 text-left transition-colors hover:bg-zinc-100 dark:bg-zinc-800/60 dark:hover:bg-zinc-800\"\n      >\n        <svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\" width=\"14\" height=\"14\" className=\"text-zinc-500 dark:text-zinc-400\">\n          <path d=\"M9.18 9.5a3 3 0 0 0 2.42 4.73\" />\n          <path d=\"M12 2a10 10 0 1 0 10 10\" />\n          <path d=\"M12 6v4l3 2\" />\n        </svg>\n        <span className=\"text-[13px] font-medium text-zinc-700 dark:text-zinc-200\">{title}</span>\n        {activeStep >= 0 && activeStep < steps.length ? (\n          <span className=\"flex items-center gap-1.5 text-xs text-zinc-500 dark:text-zinc-400\">\n            <span className=\"h-3 w-3 animate-spin rounded-full border-2 border-zinc-300 border-t-zinc-600 dark:border-zinc-700 dark:border-t-zinc-300\" />\n            Step {activeStep + 1} of {steps.length}\n            {elapsed && ` · ${elapsed}`}\n          </span>\n        ) : (\n          <span className=\"text-xs text-zinc-500 dark:text-zinc-400\">\n            {doneCount} {doneCount === 1 ? \"step\" : \"steps\"} · {steps.length} total\n          </span>\n        )}\n        <span className=\"ml-auto text-zinc-400 dark:text-zinc-500\">\n          <ChevronIcon open={open} />\n        </span>\n      </button>\n\n      {open && (\n        <ol className=\"border-t border-zinc-200 p-2 dark:border-zinc-800\">\n          {steps.map((step, i) => {\n            const state = i < activeStep ? \"done\" : i === activeStep ? \"active\" : \"pending\";\n            return (\n              <li\n                key={step}\n                className={`flex items-start gap-2.5 rounded-lg px-2 py-1.5 ${\n                  state === \"active\" ? \"bg-zinc-100 dark:bg-zinc-800/80\" : \"\"\n                }`}\n              >\n                <span className=\"mt-[3px] flex h-4 w-4 shrink-0 items-center justify-center\">\n                  {state === \"done\" && (\n                    <span className=\"flex h-4 w-4 items-center justify-center rounded-full bg-emerald-100 text-emerald-600 dark:bg-emerald-900/40 dark:text-emerald-400\">\n                      <CheckIcon />\n                    </span>\n                  )}\n                  {state === \"active\" && (\n                    <span className=\"h-3.5 w-3.5 animate-spin rounded-full border-2 border-zinc-300 border-t-zinc-600 dark:border-zinc-700 dark:border-t-zinc-300\" />\n                  )}\n                  {state === \"pending\" && (\n                    <span className=\"h-1.5 w-1.5 rounded-full bg-zinc-300 dark:bg-zinc-700\" />\n                  )}\n                </span>\n                <span\n                  className={`text-[13px] leading-5 ${\n                    state === \"done\"\n                      ? \"text-zinc-600 dark:text-zinc-300\"\n                      : state === \"active\"\n                        ? \"font-medium text-zinc-800 dark:text-zinc-100\"\n                        : \"text-zinc-500 dark:text-zinc-400\"\n                  }`}\n                >\n                  {step}\n                </span>\n              </li>\n            );\n          })}\n        </ol>\n      )}\n    </div>\n  );\n}\n","type":"registry:ui","target":"components/ui/reasoning-steps.tsx"}]}