Skip to content

Components · Workflow

Stepper

Multi-step progress for wizards and onboarding: horizontal or vertical, current, complete, error and optional steps.

@rookcom/monarch-react/patternsComponent

Wizard with clickable completed steps

Usage examples

Error and descriptions

Vertical

Compact

Purpose

Shows where the user is in a fixed sequence of steps, what is done and what is left, and optionally lets them jump back to a finished step. Import from @rookcom/monarch-react/patterns.

Use when

  • A wizard or setup flow with three to seven named steps (create a community, import a file, connect a domain).
  • A record that moves through ordered stages, shown read-only (a payroll run, a filing journey).

Avoid when

  • Sections the user can visit in any order: use Tabs.
  • Progress of one task with no named steps: use Progress.
  • A to-do list of independent tasks: use a checklist.

Design principles

  • Status is never colour alone: a check for complete, “!” for error, the number otherwise, plus hidden text (“completed”, “needs attention”).
  • The current step is the strongest element: accent ring and semibold label.
  • Connectors fill with the accent as steps complete, so progress reads at a glance.
  • Navigation is opt-in: only with onStepSelect do reachable steps become buttons; the current and future steps never are.
  • When there is no room it says less, not smaller: “Step 2 of 5 · Access” with a bar.

API reference

import { Stepper, stepStatus } from '@rookcom/monarch-react/patterns';
ExportKindRenderingRoot class
Steppercomponentserver-safe.mn-stepper
stepStatusutilityserver-safe–

Renders <nav aria-label="Progress"> (ref) with an <ol>; each step is an <li> with data-status and, for the current step, aria-current="step".

steps are { id, label, description?, optional?, status?, disabled? }; status overrides the derived state with error or complete.

current and furthest take a step id or a zero-based index. stepStatus(index, currentIndex, step) is exported to derive the same status elsewhere.

Generated from the TypeScript declarations of packages/react/src/components/workflow/stepper.

Properties

Stepper

Multi-step progress for wizards, onboarding and setup flows. An ordered list inside a `nav` with `aria-current="step"` on the current step; finished steps can be made clickable. Collapses to "Step 2 of 5" with a progress bar when there is no room.

PropTypeDescription
current requiredstring | numberThe current step: its `id` or its zero-based index. Steps before it are complete.
steps requiredStepperStep[]The steps, in order.
classNamestring
compact"auto" | "always" | "never"When to show the compact "Step 2 of 5" summary with a progress bar instead of the full list. `auto` (default) switches when a horizontal stepper's own width is under 36rem, so it collapses at 320px and in narrow panels.
furtheststring | numberThe furthest step the user has reached (id or index), when they have gone back. Steps up to it stay clickable. Default: the current step.
idstring
messagesPartial<StepperMessages>Override visible and announced strings.
onStepSelect((step: StepperStep, index: number) => void)Makes reachable steps (complete ones and any up to `furthest`) buttons that call this with the step and its index. Without it the stepper only shows progress.
orientation"horizontal" | "vertical"Default `horizontal`. A vertical stepper suits a sidebar or a long setup checklist.

Variants

PropValuesDescription
orientation'horizontal''vertical'horizontal (default) spreads steps across with connectors; vertical stacks them for sidebars and checklists, and never collapses.
compact'auto''always''never'auto (default) collapses a horizontal stepper to the “Step n of m” summary when its own width is under 36rem (a container query), so it adapts to 320px screens and narrow panels.

States

StateExposed asBehaviour
Currentdata-status="current", aria-current="step"Accent ring and number, semibold label.
Completedata-status="complete"Filled accent circle with a check; the following connector is accent.
Upcomingdata-status="upcoming"Outlined circle with the number, muted label.
Errordata-status="error"Filled danger circle with “!”, danger label.
Optional–“Optional” under the label (messages.optional).
Clickablebutton[data-clickable]Hover fill and underline; focus ring.
Disableddata-disabledA step that would be clickable but is disabled: disabled label colour.

Interaction behaviour

  • Steps before current are complete. With onStepSelect, complete steps and steps up to furthest (after going back) are buttons that call it with the step and its index.
  • The current step, future steps beyond furthest and disabled steps are plain text.
  • The stepper does not move focus; on a step change, move focus to the new step’s heading in your page so screen-reader users hear where they are.

Keyboard support

KeysAction
TabMoves between clickable steps (only reachable steps are buttons).
Enter / SpaceGoes to the focused step.

A read-only stepper has no tab stops.

Accessibility

Role
navigation containing an ordered list
Accessible name
aria-label on the nav, default “Progress”; name it after the flow (“Setup progress”).
  • aria-current="step" marks the current step.
  • Each step includes hidden text “Step n of m:” and, when relevant, “(completed)” or “(needs attention)”, so buttons are fully named.
  • Indicator numbers, checks and the compact bar are aria-hidden; the text carries the information.
  • In compact mode the list is not displayed and the summary text (“Step 2 of 5 Access”) is read instead.
  • Verified with axe in jsdom and in Chromium, Firefox and WebKit on /components/stepper.

Responsive behaviour

  • Horizontal steps share the width; labels wrap rather than overflow.
  • Under 36rem of its own width (compact="auto") it shows “Step 2 of 5 · label” and a progress bar, so at 320px nothing is cramped.
  • Vertical steppers keep the full list at every width.

Theme support

  • Monarch tokens only: --mn-color-accent-solid for complete and current, --mn-color-danger-solid for errors, --mn-color-border-strong for upcoming outlines.
  • Follows the product accent; forced-colours mode draws indicators in Highlight.
  • The hover transition is removed under prefers-reduced-motion: reduce.

Do and don't

Do

  • Keep labels to one or two words, and keep the step count small (three to seven).
  • Mark steps with problems status: "error" and jump the user to the first one on submit.
  • Pair the stepper with Back / Continue buttons; the stepper is not the only way forward.

Don't

  • Do not make future steps clickable when earlier steps validate what they need.
  • Do not use a stepper for tabs or for free-order sections.
  • Do not rely on the step colour to explain an error; say what is wrong in the step itself.
  • Progress: Progress of one task without named steps; also the bar in compact mode.
  • Tabs: Sections in free order.
  • OnboardingChecklist: Independent tasks the user ticks off in any order.

Dependencies

KindDepends on
npm packagesreact
Monarch componentsProgress

Testing coverage

  • Named nav and ordered list; aria-current="step"; complete/current/upcoming statuses; hidden “Step n of m” and status text; description and optional note; axe.
  • Current by index (clamped) and by id.
  • Error and out-of-order complete overrides; axe.
  • No buttons without onStepSelect; with it only completed steps are buttons, clicked or activated with Enter; axe.
  • furthest keeps later reached steps clickable after going back; disabled steps are not.
  • Compact summary with an aria-hidden bar; vertical orientation.
  • Translated messages; stepStatus; renders on the server.
CheckCovered
Axe in jsdomYes
Server renderingYes
Browser suitesVisual baselines: /__gallery/stepper; Cross-browser axe: /components/stepper

Tests: packages/react/src/components/workflow/stepper