{ "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "timeline", "type": "registry:component", "title": "Vertical timeline", "description": "Three-axis state story: solid past, dotted future, donut current; terminal failure is never a green check.", "registryDependencies": [ "@venlyfinance/venly-tokens" ], "files": [ { "path": "registry/components/timeline.tsx", "type": "registry:component", "target": "~/components/venly/components/timeline.tsx", "content": "import type { CSSProperties, ReactElement, ReactNode } from \"react\";\n\n/**\n * Vertical timeline – status story for one money movement.\n *\n * Design contract encoded by this component:\n * - State is distinguished on three axes at once: node, rail below, label.\n * - Solid rail = past, dotted rail = future; the switch happens at the\n * current node. Never inverted.\n * - Current node = accent donut + bold label. Future = hollow node, grey\n * regular label.\n * - Terminal failure/cancellation: the node goes neutral grey or danger,\n * NEVER a success-green check – a green check on a cancelled step makes\n * the timeline read \"all good\" at a glance (the most dangerous timeline\n * error observed in the reference corpus).\n */\nexport type TimelineStepState = \"completed\" | \"current\" | \"future\" | \"failed\" | \"cancelled\";\n\nexport interface TimelineStep {\n key: string;\n label: ReactNode;\n /** Completion word, timestamp, or estimate. */\n meta?: ReactNode;\n state: TimelineStepState;\n}\n\nexport interface TimelineProps {\n steps: TimelineStep[];\n style?: CSSProperties;\n className?: string;\n}\n\nconst NODE_SIZE = \"var(--timeline-node)\";\n\nfunction Node({ state }: { state: TimelineStepState }): ReactElement {\n const base: CSSProperties = {\n width: NODE_SIZE,\n height: NODE_SIZE,\n borderRadius: \"50%\",\n display: \"inline-flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n fontSize: \"calc(var(--timeline-node) * 0.625)\",\n lineHeight: 1,\n flex: \"none\",\n };\n switch (state) {\n case \"completed\":\n return (\n \n ✓\n \n );\n case \"current\":\n return (\n \n \n \n );\n case \"failed\":\n return (\n \n ✕\n \n );\n case \"cancelled\":\n return (\n \n ↺\n \n );\n case \"future\":\n return (\n \n );\n }\n}\n\nexport function Timeline({ steps, style, className }: TimelineProps): ReactElement {\n return (\n