Designer view

Stepper

A sequential multi-step indicator that visualises progress through an ordered process — checkout flows, signup wizards, multi-step forms, onboarding sequences. Distinct from Tabs (which switches between non-sequential parallel views) by enforcing order: steps complete in sequence, prior steps may be revisited but later steps are gated until prior steps validate. Distinct from Accordion (independent collapsible regions) by the strict sequence and the visible progress-through-N-steps state.

When to use

Use

For sequential multi-step processes where the order matters and progress through-the-flow is meaningful — checkout flows, signup wizards, multi-step forms, onboarding sequences, document signing flows. The user must (or typically does) complete the steps in sequence; their progress is visible at all times.

Avoid

For parallel views of the same content — that is `Tabs`. For independent collapsible regions — that is `Accordion`. For navigation between top-level pages — that is `SidebarNav`. For sequences exceeding ~7 steps — redesign as a wizard with phase grouping or as a multi-page flow.

Versus related

  • tabs

    `Tabs` is parallel — peer panels switchable in any order. `Stepper` is sequential — ordered steps that complete in sequence. The semantic distinction drives the role (`role="tablist"` with `aria-selected` vs `<ol>` with `aria-current="step"`). Use Tabs for non-sequential views; Stepper for ordered progress.

  • accordion

    `Accordion` is a list of independent collapsible regions; `Stepper` is a sequential progression with gating between steps. Accordion items are peers with no ordering; Stepper steps are ordered and gated. They look superficially similar (vertical list of expandable items) but the semantic distinction is clear in canonical usage.

  • sidebar-nav

    `SidebarNav` navigates between independent pages with their own URLs; `Stepper` shows progress within a single multi-step flow. SidebarNav is persistent global navigation; Stepper is contextual to the current flow.

  • progress-bar

    A `ProgressBar` shows continuous progress as a percentage or fraction; `Stepper` shows discrete step-by-step progress with named milestones. Progress bars are for indeterminate or percentage-based progress (file upload, page load); Stepper is for named-step processes (checkout, wizard).

Highlight
Fig 1.1 · Stepper · Designer view
Designer

Figma anatomy

Slot Figma type Hint
root frame Auto-layout horizontal frame (or vertical depending on orientation); equal-distributed steps with connectors between
step instance Step component instance with state variants (pending / active / completed / error)
step-indicator instance Step indicator component instance with number / checkmark / error icon variants
step-label text Label text style; bound to a component property
step-description text Description text style; muted; visibility per variant
connector rectangle 2px line between consecutive step indicators; style varies by adjacent step states
Designer

Token usage per slot

root
spacing
  • gapspacing.compact
  • paddingspacing.tight
step
spacing
  • paddingspacing.tight
radius
  • cornerradius.sm
step-indicator
radius
  • cornerradius.full
color
  • backgroundcolor.surface.sunken
  • foregroundcolor.text.muted
  • bordercolor.border.subtle
typography
  • sizetext.sm
  • weightweight.semibold
step-label
color
  • foregroundcolor.text.primary
typography
  • sizetext.sm
  • weightweight.medium
step-description
color
  • foregroundcolor.text.muted
typography
  • sizetext.xs
connector
color
  • backgroundcolor.border.subtle
Both

Figma ↔ Code property map

FigmaTypeCodeNotes
VariantVariantvariantMaps standard / dot / vertical. Dot variant hides labels visually (kept in DOM for SR).
SizeVariantsizesm / md / lg. Drives indicator size and typography.
Non LinearBooleannonLinearToggles whether future steps are reachable. Default false (linear sequence).
Has DescriptionsBooleanhasDescriptionsToggles per-step description slot. Useful for verbose steppers; omit for concise dot or icon-only patterns.
Step CountVariantsteps.lengthFigma exposes 3/4/5/6+ step counts as Variant for preview; code accepts an array of step definitions.
Active StepVariantactiveStepFigma exposes "step 1 active / step 2 active / etc." as Variant for state preview; in code it is a controlled prop (active step index or id).
Completed StepsVariantcompletedStepsFigma exposes "0 / 1 / 2 completed" as Variant for state preview; in code it is derived from per-step state.
Designer

Motion

TransitionDuration token
stateTransitionmotion.duration.base
activeIndicatormotion.duration.fast
Easing
motion.easing.standard
Reduced motion
Instant (jump cut)
Designer

Responsive behaviour

BreakpointChange
breakpoint.smAt and below, the canonical default switches to `variant: vertical` regardless of authored orientation — narrow viewports cannot accommodate horizontal steppers with labels and connectors. Vertical orientation accommodates labels naturally. Step descriptions may collapse to active-step-only (only the current step shows its description) to save space.
breakpoint.mdAbove this width, the authored variant renders. Horizontal stepper for short flows; vertical for flows with rich descriptions per step.
Both

Internationalisation

RTL · mirroring

Horizontal stepper direction reverses logically — first step at inline-start (visual right in RTL). ArrowKey navigation follows visual direction (ArrowLeft moves to next step in RTL per APG list navigation). Connector orientation is direction- neutral for vertical orientation; reverses for horizontal. Step indicator number / checkmark glyph is direction-neutral. Step labels inherit document direction.

Text expansion

Step labels grow with translation. Long-text languages (DE / RU / FI) may force horizontal stepper layouts to wrap or overflow; the canonical fallback at and below `breakpoint.sm` is to switch to vertical orientation regardless of authored value. For 4+ steps with long labels, vertical orientation is the safer canonical default in international layouts.

Both

Variants, properties, states

Variants

Structurally different versions of the component.

standarddotvertical

Properties

The same component, parameterised.

PropertyType
nonLinearboolean
hasDescriptionsboolean
sizesm | md | lg

States

Browser/user-driven (interactive) vs. app-driven (data).

KindStates
interactive
hoverfocus-visibledisabled
data
pendingactivecompletederror
Both

State transitions

FromToTrigger
pendingactiveUser progresses to this step — by completing the prior step (linear mode) or by clicking the step directly (`nonLinear: true`). The previously- active step transitions out of active; this step becomes active and `aria-current="step"`.
activecompletedUser completes the current step (validation passes, "Next" activated). The step transitions out of active; the next step becomes active. The completed step's indicator changes to a checkmark.
activeerrorUser attempts to advance from this step but validation fails. Step gains error state; the step's indicator changes to error glyph; an inline error message describes the failure. Stays as the active step — the user must resolve the error before advancing.
erroractiveUser resolves the validation error. State returns to active; error indicator clears.
completedactiveUser navigates back to a previous step (per `nonLinear: true` or the canonical "user may revisit prior steps" pattern). Previously-active step transitions to its appropriate state (typically pending if not yet completed, or completed if revisiting after completion).
Both

Figma↔Code mismatches

  1. 01
    Figma

    Stepper drawn as horizontal Tabs

    Code

    A list of steps with `aria-current="step"` plus order semantics

    Consequence

    Designers may use Tabs visually for sequential flow. Implementations following the design ship `role="tablist"` with `aria-selected` instead of `aria-current="step"`. SR users hear "tab" with no sense of sequence; the "X of N steps" announcement is missing; users navigate between tabs and bypass step ordering.

    Correct

    Distinguish at the canonical level: Stepper is sequential and ordered; Tabs is parallel and switchable. The semantic distinction drives the role (`<ol>` / `role="list"` vs `role="tablist"`) and the state (`aria-current="step"` vs `aria-selected`). Use Tabs for parallel views; Stepper for sequential progression.

  2. 02
    Figma

    Step indicator drawn but no accessibility for "step N of M"

    Code

    Each step carries visually-hidden "Step 2 of 5" text in addition to the indicator number

    Consequence

    Designers compose mocks with the indicator showing "2" inside a circle. Implementations following the design ship the visual indicator only; SR users hear the indicator number announced as a digit but without context — they do not know how many steps remain or which step is current.

    Correct

    Pair the visual indicator with visually-hidden text composing the position into the step's accessible name: "Step 2 of 5, Shipping, current". The visually-hidden text composes via `aria-describedby` or directly inside the step container. The indicator number itself can be `aria-hidden`.

  3. 03
    Figma

    Sequential and non-linear stepper drawn as the same component

    Code

    A `nonLinear: boolean` property that gates whether the user may click prior or future steps

    Consequence

    Designers do not distinguish linear (one-direction- only) from non-linear (jump-anywhere). Implementations following the design may ship the wrong mode; users expecting to jump to a future step in linear mode get blocked silently; users expecting linear sequence in non-linear mode skip required steps and the underlying flow breaks downstream.

    Correct

    Document `nonLinear` as a first-class property. Linear (default false): only completed and current steps are reachable; future steps are `aria-disabled`. Non-linear (true): all steps reachable; user navigates freely. Visual treatment communicates the mode (disabled-future- steps in linear mode are clearly muted and unclickable).

  4. 04
    Figma

    Connectors drawn as a single uniform line

    Code

    Connectors with style per adjacent-step-state pair (solid for completed-to-completed, muted for pending)

    Consequence

    Designers may use one connector style throughout for visual simplicity. Implementations following the design ship a single uniform line; users cannot distinguish completed sequence from pending sequence visually. The progress-through-N-steps story is lost.

    Correct

    Connector style varies based on the states of its flanking steps. Solid line for completed-to-completed (or completed-to-active); muted dashed or thinner line for pending-to-pending. Visually communicates progress-flow direction. Decorative — the canonical semantic still lives in `aria-current` and step states.

Designer

Common mistakes

#stepper-no-aria-current

Active step missing `aria-current`

Problem

Visual active step is shown via background colour or indicator emphasis; `aria-current="step"` is missing. SR users hear no signal of which step is active; they cannot orient to the position in the sequence.

Fix

The active step carries `aria-current="step"` (the canonical APG-recommended value for sequence steps). SR announces "current step" before the step's label. Update on every step transition.

#stepper-skip-validation

Linear stepper allows skipping required steps

Problem

User clicks step 4 in linear mode while step 2 is incomplete; the click navigates them there regardless. Required validation per step is bypassed; the underlying flow breaks downstream.

Fix

In linear mode (`nonLinear: false`), future steps are `aria-disabled` until prior steps complete. Click is a no-op (or shows a "complete prior steps first" message). The "Next" button is the canonical forward-navigation; clicking step indicators directly is allowed for prior steps but not future steps.

#stepper-step-not-button

Interactive step not a button

Problem

Implementation makes step indicators clickable via onClick on a `<div>`. SR users do not get button semantics; keyboard users cannot activate via Enter / Space; focus management is bespoke.

Fix

For interactive steps (any step the user may navigate to via click), wrap in `<button>` (or `<a>` for stepper-as-navigation patterns where each step has its own URL). Standard button semantics apply: focus, Enter / Space activation, accessible name from text content.

#stepper-no-keyboard-nav

Steps reachable only via mouse

Problem

Implementation lacks keyboard support — Tab cycles through every step but ArrowKeys do not navigate between steps; or the steps are not focusable at all.

Fix

Steps are reachable via Tab (when interactive). For non-linear steppers, ArrowLeft / ArrowRight (or ArrowUp / ArrowDown for vertical orientation) move focus between steps via roving tabindex; Enter / Space activates. Linear steppers may use Tab-only navigation since future steps are disabled.

#stepper-progress-cues-decorative-only

Progress communicated only by visual indicators

Problem

Visual indicators (numbered circles, checkmarks, coloured states) communicate progress. SR users hear no progress percentage or "step N of M" composition. The visual story is rich; the accessible story is empty.

Fix

Compose visually-hidden "Step N of M" text into each step's accessible name. The stepper's root may additionally carry `aria-valuenow` / `aria-valuemin` / `aria-valuemax` if treating the stepper as a progress indicator (rare; usually the per-step announcement is sufficient).

Accessibility hints
Slot Accessibility hint
root Apply `role="list"` (or `<ol>` for the canonical ordered-list semantic) plus `aria-label="Progress"` or "Steps". Each step is a `<li>` with role inferred or explicit. The current step also carries `aria-current="step"` to announce position to SR users.
step Each step is a `<li>` carrying state via `aria-current="step"` (current), `aria-disabled` (disabled future steps in linear mode), or no attribute (pending / completed). For interactive steppers (where the user may click prior steps to revisit), the step is wrapped in a `<button>` carrying the accessible name from the label.
step-indicator Decorative — the step's accessible state (`aria-current`, `aria-disabled`) plus visually- hidden text ("Step 2 of 5, complete") communicates state. The number / checkmark / error glyph is visual reinforcement only. SR users do not rely on the indicator glyph.
step-label Plain text. The step's accessible name. For interactive steps wrapped in `<button>`, the label is the button's text content. For dot variant (label visually-hidden), the label remains in the DOM via sr-only — never `display: none`.
step-description Plain text. SR users hear it after the label when navigating into the step. For interactive steps, the description is referenced via `aria-describedby` on the step's button to compose into the announcement.
connector Decorative — `aria-hidden="true"`. Sequence is communicated through DOM order plus the steps' position cues (`aria-current`, `aria-disabled`, visually-hidden "step N of M" text); the line is visual reinforcement.