{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "timeline",
  "title": "Timeline",
  "description": "vertical status steps joined by a line · each `done` / `current` / `upcoming` with time and note",
  "dependencies": [
    "cn@^0.4.0",
    "lucide-react@^1.52.0"
  ],
  "registryDependencies": [],
  "files": [
    {
      "path": "components/kit/timeline.tsx",
      "content": "import { cn } from 'cn';\nimport { CheckIcon } from 'lucide-react';\n\nexport type TimelineItem = {\n  title: string;\n  /** When it happened, or is expected: \"12 Jun, 10:02\", \"Expected Fri\". */\n  time?: string;\n  description?: string;\n  state: 'done' | 'current' | 'upcoming';\n};\n\ntype Props = {\n  items: TimelineItem[];\n  /** The colour of what is done: `success` for orders and deliveries, `primary` for neutral processes. */\n  tone?: 'success' | 'primary';\n  className?: string;\n};\n\nconst SPOKEN = { done: 'done', current: 'in progress', upcoming: 'not yet' } as const;\n\n/**\n * Vertical status steps joined by a line: an order, a delivery, an application. Done steps are filled with a tick,\n * the current one is ringed, upcoming ones are hollow and muted.\n */\nexport function Timeline({ items, tone = 'success', className }: Props) {\n  const fill = tone === 'success' ? 'bg-success' : 'bg-primary';\n  const ring = tone === 'success' ? 'border-success' : 'border-primary';\n  return (\n    <ol className={className}>\n      {items.map((item, i) => {\n        const last = i === items.length - 1;\n        const next = items[i + 1];\n        return (\n          <li key={`${item.title}-${i}`} className=\"flex gap-3\">\n            <span className=\"flex flex-col items-center\" aria-hidden>\n              <span\n                className={cn(\n                  'flex size-6 items-center justify-center rounded-full',\n                  item.state === 'done' && fill,\n                  item.state === 'current' && cn('bg-background border-2', ring),\n                  item.state === 'upcoming' && 'bg-background border-muted-foreground border-2'\n                )}>\n                {item.state === 'done' ? (\n                  <CheckIcon className={cn('size-3.5', tone === 'success' ? 'text-success-foreground' : 'text-primary-foreground')} strokeWidth={3} />\n                ) : item.state === 'current' ? (\n                  <span className={cn('size-2.5 rounded-full', fill)} />\n                ) : null}\n              </span>\n              {!last ? <span className={cn('min-h-4 w-0.5 flex-1', next && next.state !== 'upcoming' ? fill : 'bg-border')} /> : null}\n            </span>\n            <span className={cn('flex flex-1 flex-col gap-0.5 pt-0.5', !last && 'pb-5')}>\n              <span className={item.state === 'upcoming' ? 'text-muted-foreground' : 'font-medium'}>\n                {item.title}\n                <span className=\"sr-only\">, {SPOKEN[item.state]}</span>\n              </span>\n              {item.time ? <span className=\"text-muted-foreground text-sm\">{item.time}</span> : null}\n              {item.description ? <span className=\"text-muted-foreground text-sm\">{item.description}</span> : null}\n            </span>\n          </li>\n        );\n      })}\n    </ol>\n  );\n}\n",
      "type": "registry:component",
      "target": "components/kit/timeline.tsx"
    }
  ],
  "meta": {
    "exports": [
      "Timeline"
    ],
    "api": "<Timeline items={[{ title, time?, description?, state }]} tone? />"
  },
  "docs": "Needs the kit theme (`@kit/theme`) and a next-themes ThemeProvider (attribute=\"class\") at the root.",
  "categories": [
    "data"
  ],
  "type": "registry:component"
}