Docs
Steps

Steps

Step trail for multi-step flows: numbered badge, connector, label. Same anatomy in both orientations — horizontal on desktop, vertical below md (badges stacked, connectors vertical, each label beside its badge).

When to use

✅ Use when…🚫 Avoid when…
  • Ordered stages the user moves through — onboarding, checkout, a KYC level ladder.
  • The next stage is a call to action (link or button) and later ones are locked.
  • Unordered sections. Use Tabs.
  • A single percentage with no named stages. Use ProgressBar.

Basic

Status comes from position and flags: before currentIndex (or isComplete) → complete; at currentIndex → current; disabled → locked; otherwise next — actionable when it has href, to or onClick.

<Steps
  currentIndex={2}
  steps={[
    { title: 'Dados pessoais' },
    { title: 'Documentos' },
    { title: 'Comprovante de renda' },
    { title: 'Revisão', href: '/onboarding/review' },
  ]}
/>

Level ladder (current + CTA + locked)

<Steps
  currentIndex={0}
  steps={[{ title: 'Não verificado' }, { title: 'Silver', href: '/user/verify' }, { title: 'Gold', disabled: true }]}
/>

Router links

Steps with to render through linkAs (the framework Link); steps with href are native anchors.

import { Link as RouterLink } from 'react-router-dom';
 
<Steps linkAs={RouterLink} currentIndex={1} steps={[{ title: 'A' }, { title: 'B' }, { title: 'C', to: '/c' }]} />;

Mobile

Below md (or with layout="mobile") the trail runs vertical — the same badges and labels, stacked, with vertical connectors and each label beside its badge. It resolves by the slot's width via container query (ADR-025), so a Steps embedded in a narrow column goes vertical even on a wide screen.

<Steps layout="mobile" currentIndex={1} steps={steps} />

StepsBadge

The numbered circle is exported for custom layouts.

2
3
4

Accessibility

The trail is a <nav> named by label. The current step carries aria-current="step", locked steps aria-disabled. The actionable step is a real link or button — keyboard reachable, focus ring on its badge.

Properties

Prop
Type
Default
Description
color
string
Theme token (`theme.colors`) used as `color`. Has lower precedence than `contrast`: when both are provided, the contrast calculation wins. Stays `string` (not the typed union): `color` is also an HTML attribute (`<li color>`, etc.) and interfaces extending native props require identical types on the name collision.
containment
string
Containment marker for the `cq` channel: emits `container-type` (+ `container-name` when the string form carries one, e.g. `'inline-size card'`). Apply on the immediate wrapper of the adapting component — NEVER on page-level shells.
counterLabel
((current: number, total: number) => string)
@deprecated No longer rendered. The mobile layout is now the vertical trail (badge + connector + label), not a progress bar with a counter, so there is no counter string to localize. Accepted and ignored for source compatibility; drop it — it will be removed in the next major.
currentIndex
number
0
0-based index of the current step.
label
string
Etapas
Accessible name of the trail (`<nav aria-label>`).
layout
"auto" | "desktop" | "mobile"
auto
Force one orientation instead of following the `md` container size. `mobile` is the vertical trail.
legibility
"on-photo"
Reading-shadow preset for text over a photographic background (`on-photo`). Replaces the inline `style={{ textShadow }}` in the consumer (brasil_2030 radar, gap A3). Token emission is deferred until a 2nd consumer asks for the raw var (see backlog).
linkAs
ElementType<any, keyof IntrinsicElements>
Component rendered for steps with `to` (a router `Link`). Steps with `href` always render a native `<a>`.
pageShell
boolean
Centers the element and caps the width at `theme.layout.pageMaxWidth`. The page shell of a classic centered layout.
readable
number | boolean
Makes the `color` legible against the page surface: `true` = WCAG AA (4.5), a number sets a custom floor. Ignored with `contrast`. See the Layout Props concept page for the full semantics.
steps *
StepItem[]
Steps, in order.
transform
string
CSS `transform` value (e.g. `translate(-50%, -33px)`). Never leaks to the DOM as an attribute.

Besides the props above, every component accepts the layout props (spacing, color, flex/grid, sizing, border) — not repeated here.

See also

  • Storybook story: Components / Data Display / Steps
  • Percentage only: ProgressBar