Stepper
A read-only display of progress through a multi-step flow.
- Account, Completed
- Shipping, Current step
- Payment, Not started
- Review, Not started
import { Stepper } from "@merid/react";
export function Example() {
return (
<Stepper.Root current={1} aria-label="Checkout progress">
<Stepper.Step title="Account" />
<Stepper.Step title="Shipping" />
<Stepper.Step title="Payment" />
<Stepper.Step title="Review" />
</Stepper.Root>
);
}Import
import { Stepper } from "@merid/react";Anatomy
<Stepper.Root current={0}>
<Stepper.Step title="…" description="…" />
</Stepper.Root>Stepper.Root— an ordered list.currentis the zero-based index of the active step; earlier steps are complete, later ones upcoming.Stepper.Step— one step with a numbered marker (a check when complete), a title and an optional description.
Examples
Vertical with descriptions
- Create workspaceName and region, Completed
- Invite teamAdd up to 10 people, Completed
- Connect dataImport from CSV or an API, Current step
- Go live, Not started
<Stepper.Root current={2} orientation="vertical" aria-label="Onboarding">
<Stepper.Step title="Create workspace" description="Name and region" />
<Stepper.Step title="Invite team" description="Add up to 10 people" />
<Stepper.Step title="Connect data" description="Import from CSV or an API" />
<Stepper.Step title="Go live" />
</Stepper.Root>Responsive behaviour
In horizontal orientation, titles and descriptions stay on one line and truncate with an ellipsis; string titles keep the full text in a title attribute. The stepper measures its own width (a CSS container query, not the viewport): below 560px it switches to a compact layout where only the current step shows its title and the others collapse to their numbered or checked markers. Collapsed titles stay in the accessibility tree, so screen readers hear every step either way, and narrow columns need no JavaScript or orientation switch.
API reference
Stepper.Root
Renders <ol> and accepts all its HTML attributes.
| Prop | Type | Default | Description |
|---|---|---|---|
currentRequired | number | – | Zero-based index of the current step. Steps before it are complete. |
orientation | "horizontal" | "vertical" | "horizontal" | Layout direction. |
aria-label | string | "Progress" | Accessible name for the step list. |
ref | Ref<HTMLOListElement> | – | Forwarded ref to the list. |
Stepper.Step
Renders <li> and accepts its HTML attributes except title. Must be a direct child of Stepper.Root.
| Prop | Type | Default | Description |
|---|---|---|---|
titleRequired | ReactNode | – | Step name. |
description | ReactNode | – | Optional supporting line. |
statusLabels | Partial<Record<"complete" | "current" | "upcoming", string>> | { complete: "Completed", current: "Current step", upcoming: "Not started" } | Screen-reader status words appended to each step. |
Styling
.mrd-stepper[data-orientation]— root list,horizontalorvertical..mrd-stepper__step[data-state]—complete,currentorupcoming..mrd-stepper__marker— 28px circle:--mrd-traywhen upcoming, a 1.5px--mrd-accentring when current,--mrd-accent-softwhen complete..mrd-stepper__title/.mrd-stepper__description— text; the title turns--mrd-inkon the current step..mrd-stepper__step::after— the 1px--mrd-lineconnector between steps.
Accessibility
There is no APG pattern for steppers. It is a static ordered list — the same structure the APG landmark and list guidance recommends for structured content — and it is not interactive.
- The list is named "Progress" by default; set
aria-labelto describe the flow. - The current step has
aria-current="step". - Each step ends with a visually hidden status word ("Completed", "Current step", "Not started"), overridable with
statusLabelsfor localisation. - Markers are
aria-hidden; the number is conveyed by list position.
Steps are not focusable, so there are no keyboard interactions. If people can jump back to a step, put links or buttons inside the step content.
Guidelines
Do
Avoid
Do
Avoid