Stepper
Show progress through a sequence of steps.
Stepper shows progress through a sequence. It does not render panels or validate a form: your application owns the content and the rules for advancing.
Import
import { Stepper } from "@puzzle-ui/ui";Basic usage
Compose direct Stepper.Step children. Steps before the active step are completed automatically. Stable IDs preserve selection when steps are reordered; every step needs a unique ID in ID-based mode, and the active ID must match an available step.
Orientation and supporting text
orientation accepts "horizontal", "vertical", or a responsive object. Use description for supporting text and optional to identify a non-required step. Change device sizes to see the layout switch.
Clickable and non-linear steps
clickable turns selectable steps into buttons. By default, linear allows only the current and earlier steps to be selected. Set linear={false} to allow navigation to future steps; disabled still prevents selection.
Completed, error, and custom icons
completed overrides automatic completion. error takes precedence over other visual states. icon replaces the numeric or state indicator; keep the visible label meaningful because the indicator is hidden from assistive technology.
Controlled progress
Use activeStep with onStepChange for zero-based index selection. An external Continue action can advance progress while clickable steps allow returning to completed work. ID-based controlled selection uses activeStepId with onStepIdChange instead; do not mix the two modes.
API
Stepper
| Prop | Type | Default | Description |
|---|---|---|---|
children | ReactNode | Required | Direct Stepper.Step children. |
activeStep | number | - | Controlled zero-based index, clamped to available steps. |
defaultActiveStep | number | 0 | Initial uncontrolled index. |
onStepChange | (step: number) => void | - | Next index after user selection, including in ID mode. |
activeStepId | string | number | - | Controlled stable ID; must match an available step. |
defaultActiveStepId | string | number | - | Initial uncontrolled stable ID. |
onStepIdChange | (stepId: string | number) => void | - | Next ID after selection in ID mode. |
orientation | ResponsiveValue<"horizontal" | "vertical"> | "horizontal" | Layout direction; responsive keys are mobile, tablet, and desktop. |
clickable | boolean | false | Renders step buttons for navigation. |
linear | boolean | true | Prevents selecting steps ahead of the active one. |
className | string | - | Additional class on the root ordered list. |
dir | "ltr" | "rtl" | "auto" | - | Root direction; explicit rtl reverses horizontal keyboard navigation. |
Other native ordered-list attributes are forwarded to the root.
Stepper.Step
| Prop | Type | Default | Description |
|---|---|---|---|
id | string | number | - | Stable identifier; required on every step in ID mode. |
label | ReactNode | Required | Visible step label. |
description | ReactNode | - | Supporting text beneath the label. |
optional | ReactNode | - | Additional optional-step text. |
icon | ReactNode | - | Custom indicator content. |
completed | boolean | Before active step | Overrides automatic completion. |
error | boolean | false | Displays an error state. |
disabled | boolean | false | Prevents navigation to this step. |
className | string | - | Additional class on the step list item. |
Accessibility
Clickable steps use roving focus: arrow keys move focus (in either orientation), Home and End move to the first and last selectable step, and Enter or Space activates the focused step. With the default linear behavior, steps ahead of the active step cannot be selected.
The active list item exposes aria-current="step". Give the ordered list a descriptive aria-label when there are multiple progress indicators.