Stepper
A stepped navigation component used to guide users through a sequential multi-stage process. Use when each step must be completed in order. Don't use for more than 7 steps.
FigmaDescription
Displays a numbered sequence of steps with clear visual indicators of progress — completed, current, and upcoming — so users always know where they are in a multi-stage process.
Multi-step forms and wizards in Open Point and Social Point, such as creating a new consultation, onboarding a stakeholder, or submitting a community engagement response.
Government workflows frequently require users to provide information across several distinct stages. A stepper enforces order, reduces cognitive load by chunking the process, and provides a persistent progress indicator so users can orient themselves without re-reading the full form.
Anatomy
| Part | Required? | Notes |
|---|---|---|
| Step indicator (circle/icon) | Required | A numbered circle for upcoming and current steps; a checkmark icon for completed steps. Communicates state at a glance. |
| Step label | Required | Short text label naming the step (e.g. 'Contact details', 'Review'). Must be concise — no more than 3 words. |
| Connector line | Required | Horizontal or vertical line linking adjacent step indicators. Fills with the interactive colour as steps are completed. |
| Step subtitle | Optional | A secondary line of text below the label providing brief context (e.g. 'Required fields only'). Use sparingly. |
| Step content area | Required | The region below or beside the stepper where the active step's form or content is rendered. Not part of the stepper component itself but must be clearly associated. |
| Navigation controls | Recommended | Back and Next/Submit buttons that live below the step content. Typically a Button pair; the stepper does not render these itself. |
Variants
Horizontal
Steps are arranged left-to-right with connector lines between them.
Use for processes with 3–5 steps where horizontal space is available, such as desktop-width multi-step forms in Open Point admin views.
Vertical
Steps are stacked top-to-bottom with connector lines running between them.
Use on narrow viewports or when step labels are longer than two words. Preferred on mobile and within sidebars.
Compact
Reduced-size indicators and labels; connector lines are thinner.
Use when the stepper must coexist with dense content (e.g. inside a dialog or a narrow panel). Minimum indicator size must still meet 44x44px touch target.
States
| State | Behaviour |
|---|---|
| Upcoming | Step indicator is an outlined circle with a muted fill (--op-color-bg-secondary). Label text uses --op-color-text-secondary. Connector line to this step is unfilled. |
| Current (active) | Step indicator circle uses --op-color-interactive-default fill with white numeral. Label uses --op-color-text-primary and font-weight bold. A visible focus ring (3px, --op-color-interactive-focus) is present when the indicator has keyboard focus. |
| Completed | Step indicator shows a checkmark icon on --op-color-interactive-default background. Connector line leading to this step fills with --op-color-interactive-default. Label text uses --op-color-text-secondary. |
| Error | Step indicator shows an alert icon on --op-color-status-error background. Label uses --op-color-status-error. Use when the user returns to a step that contains a validation error. |
| Disabled | Step indicator and label use --op-color-text-disabled. The step is not clickable or focusable. Reserved for steps locked behind incomplete prerequisites. Avoid overuse — government users need to understand why a step is unavailable. |
Usage guidelines
When to use
- Creating a new consultation in Open Point that has 3 or more distinct phases (e.g. Details, Stakeholders, Notifications, Review).
- Guiding a community member through a multi-stage submission in Social Point (e.g. Personal info, Your response, Review and submit).
- Any workflow where the user must complete steps in a fixed order and progress should be saved per step.
- Onboarding flows where orientation ('you are on step 2 of 5') reduces abandonment.
When not to use
- Fewer than 3 steps — use a single form with sections or a tabbed layout instead.
- More than 7 steps — break the process into separate pages or grouped stages.
- Non-sequential workflows where steps can be completed in any order — use a task list or checklist instead.
- Simple confirmation flows — a single confirmation dialog or page is sufficient.
- Navigation between unrelated pages — use the site navigation or breadcrumbs instead.
Do / Don't
Do
Keep step labels to 1–3 words so they remain legible at all viewport widths.
Don't
Don't use full sentences or questions as step labels (e.g. 'What are your contact details?' is too long).
Do
Save progress at each step so users can return without losing data.
Don't
Don't require users to restart the entire process if they navigate away or their session expires.
Do
Allow users to navigate back to completed steps to review or edit their answers.
Don't
Don't lock completed steps — government users frequently need to check earlier answers before submitting.
Do
Show validation errors inline within the step content, and reflect the error state on the step indicator.
Don't
Don't show a generic error at the top of the page without indicating which step contains the problem.
Do
Use the vertical variant on mobile viewports.
Don't
Don't force a 5-step horizontal stepper on a 375px screen — labels will truncate or overflow.
Layout & Spacing
Horizontal stepper:
- Indicator diameter: 32px (compact: 24px)
- Gap between indicator and label: --op-space-8 (8px)
- Gap between step columns: --op-space-32 (32px) minimum
- Connector line height: 2px; fills horizontally from left
Vertical stepper:
- Indicator diameter: 32px (compact: 24px)
- Gap between indicator and label: --op-space-12 (12px)
- Row gap between steps: --op-space-24 (24px)
- Connector line width: 2px; runs vertically between indicators
Navigation controls below step content:
- Margin top from content: --op-space-32 (32px)
- Back button: secondary variant, left-aligned
- Next/Submit button: primary variant, right-aligned or left of Back on mobile
Tokens
| Part | Token | Value |
|---|---|---|
| Indicator — upcoming | --op-color-bg-secondary | Fill; border uses --op-color-border-default |
| Indicator — current | --op-color-interactive-default | Fill (green-400); numeral in white |
| Indicator — completed | --op-color-interactive-default | Fill; checkmark icon in white |
| Indicator — error | --op-color-status-error | Fill; alert icon in white |
| Indicator — disabled | --op-color-bg-secondary | Fill; numeral uses --op-color-text-disabled |
| Connector line — incomplete | --op-color-border-default | Unfilled connector |
| Connector line — complete | --op-color-interactive-default | Filled connector leading into a completed step |
| Step label — current | --op-color-text-primary | Bold weight via --op-font-body |
| Step label — upcoming / completed | --op-color-text-secondary | Regular weight |
| Step label — error | --op-color-status-error | Communicates error state in label |
| Step label — disabled | --op-color-text-disabled | |
| Focus ring | --op-color-interactive-focus | 3px solid, offset 2px, on indicator when focused |
| Step subtitle | --op-color-text-secondary | --op-text-xs; only visible for current and upcoming steps |
Engineering notes
- The stepper is a presentational component. Step state (upcoming, current, completed, error, disabled) is managed by the parent form or wizard controller.
- Wrap the stepper in a
- Each step indicator should be an
- list item so the total step count is announced by screen readers.
- The current step's
- should carry aria-current='step'. Completed steps should use aria-label that includes 'completed' (e.g. 'Step 1: Details, completed').
- Do not use anchor tags for non-navigable upcoming or disabled steps. Use
- Connector lines are decorative — use aria-hidden='true' on the connector element.
- For vertical layout on small screens, use a CSS custom property or a data attribute (data-orientation='vertical') to switch layout rather than a separate component.
- Persist step data to sessionStorage or server-side on each Next action so users can recover from session interruptions — especially important in government-facing submission flows.
- Avoid animating connector fill if prefers-reduced-motion is set. Use CSS: @media (prefers-reduced-motion: reduce) { .stepper-connector { transition: none; } }
Keyboard interaction
| Key | Action |
|---|---|
| Tab | Moves focus to the next interactive element. Completed step indicators (if clickable) receive focus in DOM order. |
| Shift+Tab | Moves focus to the previous interactive element. |
| Enter | Activates a completed step indicator (if implemented as a button) to navigate back to that step. |
| Space | Activates a focused button-type step indicator. |
Why it matters
Government digital services must meet WCAG 2.1 AA. Many users of Open Point and Social Point access services using assistive technology or keyboard-only navigation. A stepper that relies solely on visual position or colour to communicate progress will fail these users. Screen reader users need to hear which step they are on, how many steps there are in total, and whether previous steps are complete or have errors.
Focus
When the user advances to the next step (via the Next button), focus should move to either:
- The heading of the new step's content area, or
- The first interactive element within the new step content. Do NOT move focus to the step indicator itself on step transition — the indicator is not the interactive destination. Completed step indicators that allow back-navigation must be focusable buttons with a visible 3px focus ring using --op-color-interactive-focus.
ARIA
| Role or attribute | When to use | Example |
|---|---|---|
nav (landmark) | Wrap the entire stepper in | <nav aria-label="Progress"><ol class="stepper">...</ol></nav> |
aria-current="step" | Apply to the | <li aria-current="step">Step 2: Stakeholders</li> |
aria-label (on completed steps) | Override the visible label to include completion status so screen readers announce it. | <li aria-label="Step 1: Details, completed"> |
aria-label (on error steps) | Include error status in the accessible label. | <li aria-label="Step 3: Review, contains errors"> |
aria-disabled="true" | Apply to disabled step indicators rendered as buttons. | <button aria-disabled="true">Step 4: Submit</button> |
aria-hidden="true" | Apply to decorative connector lines and icon SVGs inside indicators. | <span class="connector" aria-hidden="true"></span> |
Contrast
- Indicator fill (--op-color-interactive-default, green-400) with white numeral/icon must meet 4.5:1 for normal text or 3:1 for large/bold icons. Verify at implementation.
- --op-color-status-error fill with white icon must meet 3:1 minimum for the icon size used.
- Step labels (--op-color-text-secondary on --op-color-bg-primary) must meet 4.5:1.
- Disabled labels (--op-color-text-disabled) are exempt from contrast requirements per WCAG 1.4.3 but should remain legible enough to identify the step name.
- Focus ring: --op-color-interactive-focus at 3px must meet WCAG 2.4.11 (focus appearance, AA) — verify against the background behind the indicator.
Touch targets
Each clickable step indicator must be at least 44x44px. The default 32px indicator diameter is below this threshold — implement a transparent hit-area padding around the indicator to meet the minimum. In compact variant, the 24px indicator requires even more padding.
Things to avoid
- Using colour as the sole differentiator between step states.
- Removing focus styles or overriding outline: none on step indicators.
- Rendering upcoming/disabled steps as — this confuses screen readers that announce them as links.
- Announcing step transitions with an ARIA live region on every keystroke — only announce on deliberate step navigation.
- Truncating step labels with an ellipsis without providing the full label in an aria-label or title attribute.