Stepper
Part of the extras bundle, not included by default.
Intent
A horizontal sequence of numbered steps that tells the user
where they are in a multi-screen flow -- account creation,
checkout, onboarding wizards, settings migrations. State
rides on badge color (success for done, accent for current,
neutral for upcoming) and on
aria-current="step" for the active step's
label weight.
The stepper is mostly composition reuse:
.cluster
handles the horizontal layout,
.badge.as-circle
paints the numbered indicator, and
.divider
+ a stepper-specific
.stepper-connector modifier fills the gap
between steps. The stepper file just adds a thin layer of
glue.
Basic usage
<nav class="cluster stepper" aria-label="Progress">
<span class="step">
<span class="badge as-circle is-success" aria-label="Complete">✓</span>
<span class="step-label">Account</span>
</span>
<hr class="divider stepper-connector"/>
<span class="step" aria-current="step">
<span class="badge as-circle is-accent">2</span>
<span class="step-label">Profile</span>
</span>
<hr class="divider stepper-connector"/>
<span class="step is-upcoming">
<span class="badge as-circle is-neutral">3</span>
<span class="step-label">Preferences</span>
</span>
<hr class="divider stepper-connector"/>
<span class="step is-upcoming">
<span class="badge as-circle is-neutral">4</span>
<span class="step-label">Review</span>
</span>
</nav>
The active step takes aria-current="step";
brio auto-bolds its .step-label via the
attribute selector. Upcoming steps add
.is-upcoming on the .step to mute
the label color.
Checkmarks for completed steps
Replace the step number with a checkmark glyph for completed
steps. Pair the badge with
aria-label="Complete" so assistive tech
announces what the symbol means.
<nav class="cluster stepper" aria-label="Progress">
<span class="step">
<span class="badge as-circle is-success" aria-label="Complete">✓</span>
<span class="step-label">Account</span>
</span>
<hr class="divider stepper-connector"/>
<span class="step">
<span class="badge as-circle is-success" aria-label="Complete">✓</span>
<span class="step-label">Profile</span>
</span>
<hr class="divider stepper-connector"/>
<span class="step" aria-current="step">
<span class="badge as-circle is-accent">3</span>
<span class="step-label">Preferences</span>
</span>
<hr class="divider stepper-connector"/>
<span class="step is-upcoming">
<span class="badge as-circle is-neutral">4</span>
<span class="step-label">Review</span>
</span>
</nav>Double-digit steps
The badge's as-circle shape stretches into a pill
when content widens past one character -- the circle becomes
an oval gracefully. No special markup needed.
<nav class="cluster stepper" aria-label="Progress">
<span class="step">
<span class="badge as-circle is-success" aria-label="Complete">✓</span>
<span class="step-label">Intro</span>
</span>
<hr class="divider stepper-connector"/>
<span class="step">
<span class="badge as-circle is-success" aria-label="Complete">✓</span>
<span class="step-label">Details</span>
</span>
<hr class="divider stepper-connector"/>
<span class="step" aria-current="step">
<span class="badge as-circle is-accent">10</span>
<span class="step-label">Review</span>
</span>
<hr class="divider stepper-connector"/>
<span class="step is-upcoming">
<span class="badge as-circle is-neutral">11</span>
<span class="step-label">Payment</span>
</span>
<hr class="divider stepper-connector"/>
<span class="step is-upcoming">
<span class="badge as-circle is-neutral">12</span>
<span class="step-label">Confirm</span>
</span>
</nav>Always-compact (badges only)
.stepper.is-compact hides every
.step-label at every width -- useful in card
headers, modal toolbars, mobile layouts where labels would
overrun the available space. Move the step name into an
aria-label on each badge so assistive tech still
hears it.
<nav class="cluster stepper is-compact" aria-label="Progress">
<span class="step">
<span class="badge as-circle is-success" aria-label="Step 1, Account, complete">✓</span>
<span class="step-label">Account</span>
</span>
<hr class="divider stepper-connector"/>
<span class="step" aria-current="step">
<span class="badge as-circle is-accent" aria-label="Step 2, Profile, current">2</span>
<span class="step-label">Profile</span>
</span>
<hr class="divider stepper-connector"/>
<span class="step is-upcoming">
<span class="badge as-circle is-neutral" aria-label="Step 3, Review, upcoming">3</span>
<span class="step-label">Review</span>
</span>
</nav>Condensed (responsive collapse)
.stepper.is-condensed sets
container-type: inline-size on the
<nav> and a container query collapses
labels at widths below 30rem. Wide steppers keep their
labels; narrow embeds (sidebars, narrow cards) auto-compact.
Resize the demo below to see the collapse.
<docs-resize>
<nav class="cluster stepper is-condensed" aria-label="Progress">
<span class="step">
<span class="badge as-circle is-success" aria-label="Step 1, Account, complete">✓</span>
<span class="step-label">Account</span>
</span>
<hr class="divider stepper-connector"/>
<span class="step">
<span class="badge as-circle is-success" aria-label="Step 2, Profile, complete">✓</span>
<span class="step-label">Profile</span>
</span>
<hr class="divider stepper-connector"/>
<span class="step" aria-current="step">
<span class="badge as-circle is-accent" aria-label="Step 3, Preferences, current">3</span>
<span class="step-label">Preferences</span>
</span>
<hr class="divider stepper-connector"/>
<span class="step is-upcoming">
<span class="badge as-circle is-neutral" aria-label="Step 4, Review, upcoming">4</span>
<span class="step-label">Review</span>
</span>
</nav>
</docs-resize>
Container query lengths can't be var()-driven, so
the threshold isn't tokenized. Override the rule in your own
CSS:
/* In your project CSS, after brio-extras.css */
@container (max-inline-size: 40rem) {
.stepper.is-condensed .step-label {
display: none;
}
.stepper.is-condensed .stepper-connector {
min-inline-size: var(--space-sm);
}
}
Customization
Scoped tokens drive the stepper's geometry:
--stepper-gap (between badge and label inside a
step) and --stepper-connector-min (the minimum
width of each divider connector). Override on the
.stepper root for tighter or looser layouts.
State color comes from the badge's color variants -- override
--badge-bg / --badge-color on the
badge itself if a non-standard tint is needed.
How it works
The stepper sets --cluster-wrap: nowrap on the
.cluster root so steps stay on one line.
.stepper-connector is a divider modifier with
flex: 1 (so it grows to fill the space between
steps) and zeroed margins (so the divider's default
--divider-spacing doesn't bleed into the
cluster's vertical rhythm).
The active step gets aria-current="step"; brio
binds visual treatment (label weight) to the attribute, not
a class -- consistent with breadcrumb's
aria-current="page" and pagination's
aria-current="page" wiring.
Accessibility
-
Wrap in
<nav aria-label="Progress">so the landmark is discoverable to assistive tech. -
Mark the active step with
aria-current="step". -
For checkmarked steps, add
aria-label="Complete"on the badge so the symbol's meaning reaches screen readers. -
In
.is-compactor when.is-condensedis collapsed, labels aredisplay: noneand removed from the a11y tree. Move the step name onto each badge'saria-label-- "Step 2, Profile, current" captures the position, name, and state in one announcement.
Markup
<nav class="cluster stepper" aria-label="Progress">
<span class="step">
<span class="badge as-circle is-success" aria-label="Complete">✓</span>
<span class="step-label">Account</span>
</span>
<hr class="divider stepper-connector">
<span class="step" aria-current="step">
<span class="badge as-circle is-accent">2</span>
<span class="step-label">Profile</span>
</span>
<hr class="divider stepper-connector">
<span class="step is-upcoming">
<span class="badge as-circle is-neutral">3</span>
<span class="step-label">Review</span>
</span>
</nav>
<!-- Always-compact: add aria-label on each badge -->
<nav class="cluster stepper is-compact" aria-label="Progress"> ... </nav>
<!-- Auto-collapse: container-query at 30rem -->
<nav class="cluster stepper is-condensed" aria-label="Progress"> ... </nav>
CSS Reference: Stepper
Numbered step indicator for multi-step flows
Source: src/css/extras/stepper.css
Tokens
| Token | Default | Description |
|---|---|---|
--stepper-gap | var(--gap-snug) | Gap between the badge and label inside each step |
--stepper-connector-min | var(--space-lg) | Minimum inline size of the divider connector between steps |
--cluster-wrap | nowrap | Flex-wrap override for the cluster composition |
Slots
| Slot | Description |
|---|---|
.stepper .step | Step pair containing a badge and optional label |
.stepper-connector | Divider connector line between steps |
Classes
| Class | Description |
|---|---|
.stepper | component root |
.is-compact | Always hides labels, showing badges only at every width |
.is-condensed | Auto-hides labels at narrow container widths via container query |