Target and progress shadcn's Progress is a percentage of itself. A dashboard target needs three numbers: where you are, where you should be by now, and where you finish. A bar that only knows the first is the one that reports green all quarter. npx shadcn@latest add progress Tokens this needs: --background, --foreground, --muted, --muted-foreground, --border, --status-critical, --status-nominal, --chart-1 The status, chart, scale, state and direction names are an extension, not a rename. shadcn has --destructive and five --chart-* and nothing else in this territory. ──────────────────────────────────────────────────────────────────────── // Progress.tsx ──────────────────────────────────────────────────────────────────────── /** * Progress against a target needs the pace marker, not just the fill. * * 62% of the way to a number is good news in week eleven and bad news in week * two, and a bar showing only the fill cannot tell you which. `expected` is the * position you should have reached by now, drawn as a tick, so ahead and behind * are read rather than calculated. */ export function Progress({ value, target, expected, label, unit, }: { value: number; target: number; /** Outside the graphic, so the bar stays a bar. */ unit?: string; /** Where pace says you should be. Required—the bar is misleading without it. */ expected: number; label: string; }) { const pct = Math.min(100, (value / target) * 100); const pacePct = Math.min(100, (expected / target) * 100); const behind = value < expected; return (
Pace says {Math.round(pacePct)}% by now—{behind ? "behind" : "ahead"}