Communicates progress through the ordered steps of a wizard or multi-step flow.
Use Stepper as the ordered container and compose one Step per stage of the flow. Each step takes a label, a status (incomplete, complete, critical, or caution), isCurrent for the stage the customer is on, and isDisabled for gated steps. The Stepper numbers the steps automatically and fills the connecting line green between adjacent completed steps, so the indicator always reflects real progress.
Steps usually represent real destinations in a flow. Give a Step an href to render it as a link (through PlainButton, so it uses the app's router and correctly de-activates when the step is disabled), or an onClick to render it as a button. Disabled steps drop their href and ignore clicks automatically, so future, not-yet-enabled steps can't be navigated to.
content controls what each marker shows. The default, number, prints the step's position. icon shows a per-step icon instead (completed steps still show a check). minimal renders bare dots with no numbers or labels — the lightest treatment, for read-only or quick click-through flows. Even in minimal, keep setting label: it stays available to assistive technology as the step's name.
minimal markers stay bare whatever the step's status: the completed step's check and both attention icons are dropped along with the numbers, leaving the coin's color as the only visual difference between states. Don't use minimal for a flow where a step's status carries weight — number or icon keeps the glyphs. The status is still announced either way, since that text lives on the step's control rather than in the marker.
size sets the marker (coin) size for the whole Stepper — Coin's size scale: sm, md (default), lg, or xl. The connector thickness stays constant.
By default (layout="fill") the stepper spans the full width of its container, spreading the steps evenly. Use layout="fit" for a compact stepper that hugs its content with a consistent step width and centers itself — useful when the stepper should sit centered in a wider container rather than stretch across it.
By default (orientation="horizontal") steps run in a row with the label beneath each marker. Use orientation="vertical" to stack them in a column with the label beside each marker — for a sidebar guide or a long form chunked into stages. All states, colors, and the fill-up-to-current behavior are identical; only the axis changes. (layout only applies to the horizontal orientation.)
Two of the four status values flag a step that needs going back to. critical is for a step whose errors block finishing the flow — the customer cannot submit until they are fixed. caution is for a step that wants a look but doesn't block — an unusual value, a default they may not have meant to keep, a warning from validation that isn't fatal.
The rule for choosing between them is whether the flow can still be completed: red blocks, yellow doesn't. It is the same red-versus-yellow split Pluma uses everywhere else — critical for the invalid field that stops a form being submitted, caution for the advisory that doesn't.
Each marker turns its semantic color and shows the icon that semantic carries elsewhere in Pluma (error, the circled exclamation, for critical; warning, the triangle, for caution), so the two are told apart by shape as well as hue. Each also carries visually-hidden text — "has errors" and "needs attention" — so the status is never conveyed by color alone.
These markers are a pointer, not the message. They tell someone which step to go back to; they never say what is wrong. Keep the inline field errors on the step itself, and any summary on a review step, exactly as they are — a marker complements them and must not replace them.
Give attention steps an href (or onClick) wherever the flow allows it: the point of flagging a step is that someone can get back to it.
A step can be both the one they are on and the one with the problem — coming back to fix an errored step is the ordinary case. isCurrent behaves exactly as it always does, including aria-current="step"; on the marker the status wins, keeping its red or yellow coin with the current step's accent ring drawn around it.
An attention step is not a completed one, so the connecting lines around it stay grey — the green run keeps meaning "this stretch is done".
Set status="complete" on finished steps — their marker shows a check, and the line between two adjacent completed steps turns green. Mark the stage the customer is on with isCurrent; it bolds the label and draws an accent-colored ring around the marker (keeping its neutral surface), but it doesn't color any line, so a stepper someone has jumped ahead in keeps its lines grey until the earlier steps are actually done. A step that is both complete and current keeps its solid green check marker and gains that same ring. Use isDisabled for steps that can't be reached yet because an earlier step isn't done. For the two attention statuses, see Attention statuses above.
PlumaStepper extends BoxDefault:'number'
What each step's marker shows: the auto-numbered position (number), a
per-step icon, or a bare dot with no number or label (minimal). Applies
to every step.
Default:'fill'
How steps are distributed horizontally. fill (default) spreads them across
the full width; fit makes the stepper hug its content and center itself,
with a consistent step width — for a compact stepper centered in a wider
container. Only affects the horizontal orientation.
Default:'horizontal'
Which way the steps run. horizontal (default) lays them out in a row with
the label beneath each marker; vertical stacks them in a column with the
label beside each marker — for a sidebar guide or a long, chunked form.
Default:'md'
Marker (coin) size for every step.
PlumaStepperStep extends BoxMakes the step a link to the route it represents. Rendered through
PlainButton, so it uses the app's link component and is correctly inert
when the step is disabled (the href is dropped and clicks are blocked).
Icon shown in the marker when the Stepper's content is icon. Completed
steps show a check instead, regardless of this.
Default:false
Marks this step as the one the customer is currently on — bolds the label,
fills the marker with the active treatment, and sets aria-current="step".
Default:false
Gates the step (usually because an earlier step isn't done): mutes it and makes it inert.
The step's label, shown beneath the marker. In minimal steppers it isn't
rendered visibly but is still used as the step's accessible name.
Click handler for the step. With no href, the step renders as a button;
with an href, it fires on activation alongside navigation. Not called when
the step is disabled.
Default:'incomplete'
The step's state: whether it's been completed (complete), or needs
attention — critical for a step whose errors block finishing the flow,
caution for one that needs review but doesn't block. Independent of
isCurrent and isDisabled.
critical and caution mark where the problem is; they don't describe
it. Keep the inline field errors on the step itself, and any summary on a
review step, as the actual message.