Stage progress
How far a run has got — picking, packing, shipped, delivered — as a segment each.
A list rather than a bar, because every stage has a name and a state a reader has to be able to reach one at a time. The list carries the summary as its own name — "2 of 4: Packing" — so a row in a table announces where the order is without being opened, and each segment carries its state in words under the fill: Done, In progress, Not started, Blocked. Colour is never the only signal. How far the run has got counts everything finished plus the one being worked on, and a blocked stage counts the same way an active one does, because the run reached it and stopped rather than never arriving. Done takes the accent, since a stage bar is a progress fill and that is one of the accent's five roles; pending is the track, and only blocked spends a semantic tone, because it is the one state a reader has to act on. Active is the track under a half-width accent fill — the way an indeterminate progress bar is drawn, a convention for "started, not finished" rather than a claim that the stage is half done — and it is a shape rather than a colour on purpose: a state told apart from done only by a pulse would be indistinguishable from it the moment a reader turns motion off. The pulse over that fill is CSS: its period is a multiple of --duration-slow, which both the reader's own setting and a [data-motion="reduced"] wrapper zero, and each of the two stops it outright as well (motion-reduce, and in-data-[motion=reduced]); the fill stays either way. Nothing reads the media query in JavaScript, so a page can render a stage bar on the server.
Install
npx shadcn@latest add @vibra/stage-progressNeeds the @vibra registry in your components.json — set it up once.
Examples
Every state
A run at each point it can be at, and the small size beneath them.