{ "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "milestone-stepper", "type": "registry:ui", "title": "Milestone Stepper", "description": "A vertical timeline-style stepper for showing milestones, order tracking, or project phases. Supports custom icons and multiple variants.", "dependencies": [ "lucide-react", "motion" ], "files": [ { "path": "registry/ruixenui/milestone-stepper.tsx", "content": "\"use client\";\n\nimport * as React from \"react\";\nimport { motion } from \"motion/react\";\n\nimport { cn } from \"@/lib/utils\";\n\n// ── Types ───────────────────────────────────────────────────────────────────\n\ninterface MilestoneData {\n id: string | number;\n title: string;\n description?: string;\n date?: string;\n icon?: React.ReactNode;\n}\n\ntype MilestoneState = \"completed\" | \"current\" | \"upcoming\";\n\n// ── MilestoneStepper ────────────────────────────────────────────────────────\n\ninterface MilestoneStepperProps extends React.HTMLAttributes {\n milestones: MilestoneData[];\n currentMilestone?: number;\n variant?: \"default\" | \"compact\" | \"detailed\";\n lineStyle?: \"solid\" | \"dashed\";\n}\n\nfunction MilestoneStepper({\n milestones,\n currentMilestone = 0,\n variant = \"default\",\n lineStyle = \"solid\",\n className,\n ...props\n}: MilestoneStepperProps) {\n return (\n
\n {milestones.map((milestone, index) => {\n const state: MilestoneState =\n index < currentMilestone\n ? \"completed\"\n : index === currentMilestone\n ? \"current\"\n : \"upcoming\";\n\n return (\n \n );\n })}\n
\n );\n}\n\n// ── MilestoneItem ───────────────────────────────────────────────────────────\n\ninterface MilestoneItemProps {\n milestone: MilestoneData;\n state: MilestoneState;\n isLast: boolean;\n variant: \"default\" | \"compact\" | \"detailed\";\n lineStyle: \"solid\" | \"dashed\";\n index: number;\n}\n\nfunction MilestoneItem({\n milestone,\n state,\n isLast,\n variant,\n lineStyle,\n index,\n}: MilestoneItemProps) {\n return (\n \n {/* Indicator column */}\n
\n
\n \n
\n {!isLast && (\n \n )}\n
\n\n {/* Content */}\n \n
\n
\n \n {milestone.title}\n \n {milestone.description && variant !== \"compact\" && (\n \n {milestone.description}\n

\n )}\n
\n {milestone.date && (\n \n {milestone.date}\n \n )}\n
\n \n \n );\n}\n\n// ── MilestoneIcon ───────────────────────────────────────────────────────────\n\ninterface MilestoneIconProps {\n state: MilestoneState;\n icon?: React.ReactNode;\n}\n\nfunction MilestoneIcon({ state, icon }: MilestoneIconProps) {\n if (icon) {\n return (\n \n svg]:size-2.5\">{icon}\n \n );\n }\n\n return (\n
\n {state === \"current\" && (\n \n )}\n \n
\n );\n}\n\n// ── Exports ─────────────────────────────────────────────────────────────────\n\nexport { MilestoneStepper, MilestoneItem, MilestoneIcon };\nexport type { MilestoneData, MilestoneState };\n", "type": "registry:ui", "target": "components/ruixen/milestone-stepper.tsx" } ] }