{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "task-plan",
  "title": "Task plan",
  "description": "An agent's plan on a legal pad. Finished steps are ticked in ink, the current one is underlined in red pen, the rest are still in pencil.",
  "dependencies": [
    "@base-ui/react",
    "cn"
  ],
  "registryDependencies": [
    "https://bevel-ui.vercel.app/r/bevel.json"
  ],
  "files": [
    {
      "path": "registry/bevel/ui/task-plan.tsx",
      "content": "\"use client\"\n\nimport * as React from \"react\"\nimport { Progress as ProgressPrimitive } from \"@base-ui/react/progress\"\nimport { cn } from \"cn\"\n\n/** An agent's plan on a legal pad. Each row sits on a rule. */\nfunction TaskPlan({ className, children, ...props }: React.ComponentProps<\"div\">) {\n  return (\n    <div\n      data-slot=\"task-plan\"\n      className={cn(\n        \"bevel-ruled relative w-full max-w-md overflow-hidden rounded-b-(--bevel-radius-xs) pt-(--bevel-rule-height) pb-(--bevel-rule-height) text-sm\",\n        className\n      )}\n      {...props}\n    >\n      <span\n        aria-hidden\n        data-slot=\"task-plan-binding\"\n        className=\"absolute inset-x-0 top-0 h-3 bg-(--task-plan-binding) shadow-(--bevel-depth-flush)\"\n      />\n      {children}\n    </div>\n  )\n}\n\n/** Title and progress, two rules tall. */\nfunction TaskPlanHeader({ className, ...props }: React.ComponentProps<\"div\">) {\n  return (\n    <div\n      data-slot=\"task-plan-header\"\n      className={cn(\n        \"flex h-[calc(var(--bevel-rule-height)*2)] flex-col justify-end gap-1 pr-4 pb-1.5 pl-(--task-plan-indent)\",\n        className\n      )}\n      {...props}\n    />\n  )\n}\n\nfunction TaskPlanTitle({ className, ...props }: React.ComponentProps<\"p\">) {\n  return <p data-slot=\"task-plan-title\" className={cn(\"font-semibold\", className)} {...props} />\n}\n\ntype TaskPlanProgressProps = Omit<ProgressPrimitive.Root.Props, \"children\"> & {\n  /** Visible text; defaults to \"3 of 7 done\". */\n  children?: React.ReactNode\n}\n\n/** How far along the plan is, as a pencil line inked in. */\nfunction TaskPlanProgress({\n  className,\n  value,\n  max = 100,\n  children,\n  \"aria-label\": ariaLabel = \"Plan progress\",\n  ...props\n}: TaskPlanProgressProps) {\n  return (\n    <ProgressPrimitive.Root\n      data-slot=\"task-plan-progress\"\n      value={value}\n      max={max}\n      aria-label={ariaLabel}\n      getAriaValueText={(_, v) => `${v ?? 0} of ${max} done`}\n      className={cn(\"flex items-center gap-3\", className)}\n      {...props}\n    >\n      <ProgressPrimitive.Track className=\"relative h-0.5 flex-1 overflow-hidden rounded-full bg-(--bevel-pencil)/35\">\n        {/* Inked in with scale, not width, so progress never relays out the page. */}\n        <span\n          aria-hidden\n          className=\"absolute inset-0 origin-left rounded-full bg-(--bevel-pen-blue) transition-[scale] duration-(--bevel-duration-move) ease-(--bevel-ease-out) motion-reduce:transition-none\"\n          style={{ scale: `${max ? Math.min(1, (value ?? 0) / max) : 0} 1` }}\n        />\n      </ProgressPrimitive.Track>\n      <span className=\"text-(length:--bevel-fine) text-(--bevel-paper-muted) tabular-nums\">\n        {children ?? `${value ?? 0} of ${max} done`}\n      </span>\n    </ProgressPrimitive.Root>\n  )\n}\n\nfunction TaskPlanSteps({ className, ...props }: React.ComponentProps<\"ol\">) {\n  return <ol data-slot=\"task-plan-steps\" className={cn(\"flex flex-col\", className)} {...props} />\n}\n\ntype TaskPlanStatus = \"done\" | \"current\" | \"pending\" | \"error\" | \"skipped\"\n\nconst statusText: Record<TaskPlanStatus, string> = {\n  done: \"Done\",\n  current: \"In progress\",\n  pending: \"Not started\",\n  error: \"Failed\",\n  skipped: \"Skipped\",\n}\n\ntype TaskPlanStepProps = React.ComponentProps<\"li\"> & {\n  status?: TaskPlanStatus\n}\n\n/**\n * One step, written on its rule. Done steps get a tick in ink, the current\n * one is underlined in red pen, and steps not reached yet are in pencil.\n */\nfunction TaskPlanStep({ className, status = \"pending\", children, ...props }: TaskPlanStepProps) {\n  return (\n    <li\n      data-slot=\"task-plan-step\"\n      data-status={status}\n      aria-current={status === \"current\" ? \"step\" : undefined}\n      className={cn(\n        \"relative min-h-(--bevel-rule-height) pr-4 pl-(--task-plan-indent) leading-(--bevel-rule-height) text-(--task-plan-ink)\",\n        \"data-[status=skipped]:line-through\",\n        className\n      )}\n      {...props}\n    >\n      <span\n        aria-hidden\n        className=\"absolute top-0 left-0 flex h-(--bevel-rule-height) w-(--bevel-rule-margin) translate-y-(--task-plan-sink) items-center justify-center\"\n      >\n        <StepMark status={status} />\n      </span>\n      <span className=\"sr-only\">{statusText[status]}: </span>\n      {/* Written on the line, not floating between lines. */}\n      <span\n        className={cn(\n          \"block translate-y-(--task-plan-sink)\",\n          status === \"current\" &&\n            \"underline decoration-(--bevel-pen-red) decoration-2 underline-offset-4\"\n        )}\n      >\n        {children}\n      </span>\n    </li>\n  )\n}\n\n/** The mark in the margin. The tick draws itself when a step is finished. */\nfunction StepMark({ status }: { status: TaskPlanStatus }) {\n  if (status === \"current\") {\n    return (\n      <svg viewBox=\"0 0 16 16\" className=\"size-4 text-(--bevel-pen-red)\">\n        <path d=\"M2 8h10M8 4l4 4-4 4\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\" />\n      </svg>\n    )\n  }\n  if (status === \"error\") {\n    return (\n      <svg viewBox=\"0 0 16 16\" className=\"size-4 text-(--bevel-pen-red)\">\n        <path d=\"M4 4l8 8M12 4l-8 8\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" />\n      </svg>\n    )\n  }\n  return (\n    <svg viewBox=\"0 0 16 16\" className=\"size-4 text-(--bevel-pen-blue)\">\n      <path\n        d=\"M2.5 8.5l3.5 3.5 7.5-8\"\n        fill=\"none\"\n        stroke=\"currentColor\"\n        strokeWidth=\"2.2\"\n        strokeLinecap=\"round\"\n        strokeLinejoin=\"round\"\n        pathLength={24}\n        className=\"transition-[stroke-dashoffset] duration-(--bevel-duration-move) ease-(--bevel-ease-out) [stroke-dasharray:var(--task-plan-check-length)] motion-reduce:transition-none\"\n        style={{ strokeDashoffset: status === \"done\" ? 0 : \"var(--task-plan-check-length)\" }}\n      />\n    </svg>\n  )\n}\n\nexport {\n  TaskPlan,\n  TaskPlanHeader,\n  TaskPlanTitle,\n  TaskPlanProgress,\n  TaskPlanSteps,\n  TaskPlanStep,\n}\nexport type { TaskPlanStatus, TaskPlanStepProps }\n",
      "type": "registry:ui"
    }
  ],
  "css": {
    ":root": {
      "--task-plan-binding": "oklch(0.36 0.09 25)",
      "--task-plan-check-length": "24"
    },
    "[data-slot=\"task-plan\"]": {
      "--bevel-sheet": "var(--bevel-pad)",
      "--bevel-sheet-rule": "var(--bevel-pad-rule)",
      "--bevel-sheet-margin": "var(--bevel-pad-margin)",
      "--bevel-rule-height": "2rem",
      "--bevel-rule-margin": "2.5rem",
      "--task-plan-indent": "calc(var(--bevel-rule-margin) + 0.75rem)",
      "--task-plan-sink": "0.4rem",
      "color": "var(--bevel-pad-foreground)"
    },
    "[data-slot=\"task-plan-step\"]": {
      "--task-plan-ink": "var(--bevel-pen-blue)"
    },
    "[data-slot=\"task-plan-step\"][data-status=\"pending\"], [data-slot=\"task-plan-step\"][data-status=\"skipped\"]": {
      "--task-plan-ink": "var(--bevel-pencil)"
    },
    "[data-slot=\"task-plan-step\"][data-status=\"error\"]": {
      "--task-plan-ink": "var(--bevel-pen-red)"
    }
  },
  "categories": [
    "agents"
  ],
  "type": "registry:ui"
}