Stepper
Displays the current step and completion states in a multi-step flow.
Component behavior
Stepper displays flow steps and the current position. Navigation is optional and defaults to backward navigation when enabled.
WizardNav renders a Stepper using wizard state. Use Wizard when the flow also requires content panes, validation, and footer actions.
- Flows with a defined set of named stages.
- Navigation back to completed stages.
- Named step progress visible before entering a step.
Wizard: the flow needs content panes, validation, branching, and navigation actions.
Tabs: views can be visited independently.
ProgressBar: progress is a fraction of continuous work.
Timeline: the view reports timestamped history.
Props
| Prop | Type | Default | Description |
|---|---|---|---|
steps | Step[] | — | The flow, in order. |
activeIndex | number | 0 | Index of the current step. Lower indices render complete, higher ones upcoming. Pass steps.length for a finished flow. |
activeKey | string | — | The current step by key, when an index is the wrong thing to hold. Wins over activeIndex. |
variant | "circles" | "bars" | "dots" | "panels" | "circles" | Visual variant: circles, bars, dots, or panels. State and navigation behavior are shared across variants. |
orientation | "horizontal" | "vertical" | "horizontal" | Vertical is the rail: one run of connector down the marker column, and group headings become available. |
size | "sm" | "md" | "lg" | "md" | Retunes marker, type and spacing together. |
tone | ToneProp | "primary" | Accent for complete and current markers and the filled run of line. Failed steps stay err whatever this says. |
labelPlacement | "inline" | "below" | "none" | "inline" ("none" for dots) | below centres each label under its marker and lets it wrap; none keeps the label in the accessibility tree only. |
error | boolean | string | string[] | — | true fails whichever step is current; a key (or keys) fails those steps wherever they are. Errors outrank every other state. |
completed | string[] | — | Step keys displayed as complete regardless of their position. |
skipped | string[] | — | Skipped optional step keys. Shows a dashed marker and a Skipped label when no description is supplied. |
showConnectors | boolean | true (false for bars) | Displays connectors between markers. Ignored by bars, which uses its own track. |
showNumbers | boolean | true | Numbers the markers of steps that are neither complete, failed nor skipped. Off leaves them empty unless the step has an icon. |
showDescriptions | boolean | true | Displays step descriptions and Optional or Skipped labels. |
interactive | "completed" | "all" | "none" | "completed" once onStepClick is set | Which steps are buttons. completed allows only backwards moves; all allows everything not marked disabled; none makes the strip read-only even with a handler. |
fill | boolean | true | Distributes horizontal steps evenly. Below-label connectors require equal-width columns. |
onStepClick | (index: number, step: Step) => void | — | Enables navigation, subject to interactive. Omit it and no step is a button. |
labels | Partial<StepperLabels> | — | The strip's accessible name, the Optional / Skipped words, and the hidden state text on each step. Where translations go. |
as | ElementType | "nav" when navigable, "div" otherwise | The root element. A strip nobody can click is not navigation, so it is not a nav by default. |
renderStep | (step: Step, state: StepState) => ReactNode | — | Replaces a step's marker and label. The connecting line, the button/span, the click rules and the state stay Onset's. |
renderMarker | (step: Step, state: StepState) => ReactNode | — | Replaces the marker while retaining the label column. |
Step
| Prop | Type | Default | Description |
|---|---|---|---|
key | string | — | Stable key. Also what activeKey, completed, skipped and error speak in. |
label | ReactNode | — | Step name. Clips with an ellipsis beside a marker; wraps under one. |
description | ReactNode | — | Dim second line under the label. |
icon | ReactNode | — | Replaces the step number. Completed, failed, and skipped states use their state markers instead. |
badge | ReactNode | — | Content after the step label. |
group | string | — | Uppercase heading above this step; consecutive steps repeating it sit under one. Vertical only. |
optional | boolean | — | Marks the step as optional. Displays Optional when no description is supplied. |
disabled | boolean | — | Never clickable, whatever interactive says. |
status | StepStatus | — | Overrides the status derived from activeIndex: "upcoming", "current", "complete", "skipped", or "error". |
StepState
Both render callbacks receive index, status, done, active, error, clickable, and select. select invokes onStepClick for the step.
import { Stepper } from "@solarius/onset";
import type {
Step,
StepStatus,
StepState,
StepperProps,
} from "@solarius/onset";Variants
variant selects circles, bars, dots, or panels. Variants share status values, connectors, navigation rules, and markup.
Labels under the markers
labelPlacement="below" centers labels below markers and connects the markers horizontally. Labels wrap in this placement; other placements truncate labels.
labelPlacement="none" keeps the label in the accessibility tree and drops it from the layout, for a strip that has to fit a toolbar. It is the default for dots.
Vertical
orientation="vertical" renders a rail with connectors in the marker column. Consecutive steps sharing a group receive a group heading. Wizard uses the panels variant for vertical navigation.
const steps: Step[] = [
{
key: "account",
label: "Account",
description: "Owner and billing",
group: "Tenant",
},
{
key: "region",
label: "Region",
description: "Where data lives",
group: "Tenant",
},
{ key: "database", label: "Database", group: "Infrastructure" },
{ key: "tls", label: "TLS", optional: true, group: "Infrastructure" },
{ key: "review", label: "Review", badge: "12", group: "Finish" },
];
<Stepper
steps={steps}
activeIndex={2}
orientation="vertical"
variant="panels"
/>;Step states
activeIndex marks the current position. Earlier steps are complete and later steps are upcoming. Set activeIndex={steps.length} to mark the flow complete.
Skipped and failed
A skipped optional step uses a dashed marker. An error state takes precedence over other statuses so failed steps remain identifiable.
Set skipped, error, and completed using step keys, or assign status on individual steps. error={true} marks the current step as failed.
Size and tone
size sets marker dimensions, font size, and spacing. tone sets the accent for completed markers, the current marker, and completed connectors. Failed steps use err regardless of tone.
Custom properties
Everything the component measures with is a custom property on the root, so density is tunable without restating a rule. Set them in style, or on any ancestor.
| Prop | Type | Default | Description |
|---|---|---|---|
--m-stepper-marker | length | 20px (16 / 26 at sm / lg) | Marker diameter. Also drives the connector's offset and the marker/label optical alignment, so changing it alone keeps everything lined up. |
--m-stepper-line | length | 2px | Connector thickness, and the width of the panels variant's current-step accent edge. |
--m-stepper-gap | length | var(--m-space-2) | Between a marker and its label. |
--m-stepper-pad | length | var(--m-space-1_5) | Step padding, also applied to hover and active backgrounds. |
--m-stepper-font | length | var(--m-font-size-md) | Label size. Descriptions and badges keep their own fixed steps. |
--m-stepper-bar | length | 3px | Track thickness, bars variant only. |
Navigation
onStepClick enables step buttons according to interactive. The default, "completed", permits selecting completed and skipped steps. Other steps remain noninteractive. The application handles advancement.
interactive="all" permits clicks on every step except those marked disabled. The application controls reachability.
Custom step rendering
renderMarker replaces the marker while retaining the label, truncation, and state colors. renderStep replaces marker and label content while retaining connectors, button/span semantics, click handling, focus styling, and data-state.