Stepper
<wa-stepper>
Steppers visually guide users through a process step by step, breaking content into clear, logical stages. Use them for checkout flows, multi-step setup, onboarding, or just to show the status of a process.
Set the active attribute to the name of the current <wa-step>. A stepper is a display, not a form control, and by default its steps aren't directly interactive. Pair it with your own Next/Back buttons (see Navigating Declaratively) or call its methods directly to move between steps as the user progresses. Add the clickable attribute (see Clickable) to let people click a step, or focus it and press Enter/Space, to jump straight to it.
Examples
Clickable
Add the clickable attribute to render each step as a button, so clicking it, or focusing it and pressing Enter/Space, jumps straight to it, the same as calling goTo(). Without it, steps aren't focusable, and only next()/previous()/goTo() change the active step. Disabled and locked steps render as disabled buttons.
Linear
Add the linear attribute to require steps to be completed in order. Every step past the first incomplete one renders locked, and next()/goTo() (including a data-stepper invoker, or a click/activation when clickable is also set) can't reach it until the steps before it are completed.
Combined with clickable, this gives the common checkout behavior: users can return to any completed step and advance to the next one, but can't skip ahead.
Orientation
Set the orientation attribute to vertical to stack the steps, useful in a sidebar or a narrow column.
Each connector runs from its step's marker, across the gap, to the next marker. To lengthen the connectors, increase the --gap custom property.
Set orientation to auto to lay steps out in a row and stack them when the stepper is narrower than about 6em per step, so labels stay readable on small screens. Use it for any stepper that will be shown on a phone. Resize the example to see the switch. While stacked, the stepper has the stacked custom state, so wa-stepper:state(stacked) targets it.
The default, horizontal, keeps a row at any width. Labels wrap between words, and a row that still can't fit overflows its container rather than squeezing the steps. It's the default because auto measures the stepper in the browser, so a server-rendered auto stepper renders as a row first and stacks once it hydrates.
Variant
Set the variant attribute on a step to color its marker with a semantic color. The current step uses the variant's loud fill, a completed step its normal fill, and an upcoming step a thin border in its color. The default is brand, whose upcoming steps keep a neutral border so a plain stepper reads quietly. The color is cosmetic and never changes the marker's content, like variant on a badge or callout.
To flag a step that failed or needs attention, pair the variant with an icon in the icon slot and state the reason in the label or description, so the meaning doesn't depend on color alone.
Size
A stepper is sized relative to the current font size, like a badge. Set font-size on the stepper (or an ancestor element) to change it; markers, connectors, and text scale together.
Drawing Attention
Set the attention attribute on a step to pulse or bounce to animate its marker, the same options as <wa-badge>. Use it sparingly, for the one step the user should act on next. The pulse color follows the step's accent; set the --pulse-color custom property to change it. Both animations are disabled when the user prefers reduced motion.
Description
Add the description slot to any step for supporting text under its label.
Custom Icon
Use the icon slot on a step to replace its number, checkmark, or spinner with an element such as <wa-icon>. The marker keeps its state styling, so an icon reads as completed, current, or upcoming the same way a number would.
Loading
Add the loading attribute to a step to show a spinner in its marker instead of a number, e.g. while an async transition is in progress.
Disabled
Add the disabled attribute to a step that doesn't apply to the current user. The step stays visible, so the full process is still shown, but it can't be clicked, focused, or reached with next()/goTo().
Navigating Declaratively
Add the data-stepper attribute to any button on the page, with next <id>, previous <id>, or goto <id> <name> as its value, to call next(), previous(), or goTo() on the stepper with that id. It's the same convention as <wa-dialog>'s data-dialog="open <id>", and the button doesn't need to be inside the stepper.
Reacting to Changes
The wa-step-change event fires once the active step has changed, with name and previousName in event.detail, plus the step and previousStep elements themselves. The stepper never sets completed itself. Mark a step done from your own code, e.g. once the user has advanced past it.
Pairing with Content
The stepper only shows progress; it doesn't hold the content for each step. Keep that content in your own elements and show the one that matches the active step from a wa-step-change listener. This keeps the stepper usable with any layout, from a single form panel to a full page per step.
Review the items in your cart.
Enter the address to ship to.
Add a card to pay with.
Preventing a Step Change
The wa-before-step-change event fires before the step changes and is cancelable. Call event.preventDefault() to block the transition, e.g. to guard against unsaved changes. Toggle the switch and press Continue to see the change blocked or allowed.
Customizing
Use the exported CSS parts and custom properties to restyle the stepper. This example gives completed steps the success variant, and the connector after each completed step follows it. It sets the inactive connector with the --connector-color custom property, enlarges the markers and widens the space between steps with the --marker-size and --gap custom properties, then squares off the markers and bolds their text via each step's marker part. The part belongs to <wa-step>, so the selector targets the steps, not the stepper; see the Step page for every part a step exposes.
Here the connector properties become a transit line, the marker part turns each stop into a ring, and the completed and active custom states mark the stops behind you and the one you're at. Shrink it to see orientation="auto" stack it into a strip map.
Steps share the row equally. Give a step with more content extra room by setting flex on it. The connectors meet in the middle of each gap, so uneven widths don't break the line. In a stacked layout, flex has no effect, because the column has no extra height to distribute.
Accessibility Considerations
- Structure. The stepper renders an ordered list, and each
<wa-step>carriesrole="listitem". When the stepper isclickable, the list sits in a<nav>landmark, since its steps are then controls you can navigate with; otherwise it's a labeled group, so a display-only stepper doesn't add a navigation landmark with nothing to navigate. Set thelabelattribute whenever more than one stepper appears on the same page, so screen reader users can tell them apart. Without it, the wrapper gets a generic localized name. - Current step. The active step carries
aria-current="step"on whichever element is actually focusable: the step's own host when the stepper isn'tclickable, or its inner<button>when it is. It's removed, not set to"false", everywhere else. The stepper also renders visually hidden "Step 2 of 4" text, so the position is announced without relying on the markers. - Step changes are announced. When
next(),previous(), orgoTo()changes the active step, the new position is announced to screen readers through a shared live region, so the update isn't silent even when nothing in the stepper has focus. - Step status. Each step's status is announced, not just shown. Completed steps carry visually hidden "Completed" text, pending steps "Not completed", disabled steps "Disabled", and locked steps "Locked". The checkmark itself is decorative.
- Keyboard. Steps are only in the tab order when the stepper is
clickable, and then each one is rendered as a<button>: Tab moves between them and Enter or Space activates one, the same as clicking it.disabledand locked steps render as disabled buttons, so they're skipped. Withoutclickable, nothing in the stepper takes focus, and screen readers still read every step in order. - Busy state. Each loading step carries
aria-busy="true". The stepper itself carries theloadingcustom state while any step is loading, as a styling hook. It isn't propagated to the stepper's ownaria-busy, since nesting that on the landmark can suppress announcements for the whole region. - Color and meaning. The
variantattribute is cosmetic. It changes color, which doesn't carry meaning on its own, so include the reason in the step's visible label or description, and add an icon in theiconslot when a step needs to read as failed.
API
Importing
If you're using the autoloader or a hosted project, components load on demand — no manual import needed. To cherry-pick a component manually, use one of the following snippets.
Import this component directly from the CDN:
import 'https://ka-f.webawesome.com/[email protected]/components/stepper/stepper.js';
After installing Web Awesome via npm, import this component:
import '@awesome.me/webawesome/dist/components/stepper/stepper.js';
If you're self-hosting Web Awesome, import this component from your server:
import './webawesome/dist/components/stepper/stepper.js';
To import this component for React 18 or below, use the following code:
import WaStepper from '@awesome.me/webawesome/dist/react/stepper/index.js';
Slots
Learn more about using slots.
| Name | Description |
|---|---|
| (default) | One or more <wa-step> elements. |
Attributes & Properties
Learn more about attributes and properties.
| Name | Description | Reflects |
|---|---|---|
activeactive |
The name of the active step. Falls back to the first step if unset, or if it doesn't match any step's name.
Type
string
Default
''
|
|
clickableclickable |
Allows clicking a step, or focusing it and pressing Enter/Space, to jump straight to it. When unset (the
default), only
next()/previous()/goTo() change the active step, e.g. from your own Next/Back buttons or a
data-stepper invoker.
Type
boolean
Default
false
|
|
labellabel |
A label that describes the stepper to assistive devices. Especially useful when more than one is on the page.
Type
string
Default
''
|
|
linearlinear |
Requires steps to be completed in order. When set,
next()/goTo()/a data-stepper invoker and, if
clickable is also set, clicking or activating a step can't reach a step until every step before it is
completed. Every step past that point renders as locked.
Type
boolean
Default
false
|
|
orientationorientation |
The stepper's layout direction.
auto lays steps out in a row and stacks them when the stepper is too narrow to
give each step about 6em of width, so labels stay legible on small screens; use it for anything shown on a
phone. It relies on measuring the stepper, so a server-rendered auto stepper starts as a row and stacks once
it hydrates, which is why horizontal is the default.
Type
'horizontal' | 'vertical' | 'auto'
Default
'horizontal'
|
|
Methods
Learn more about methods.
| Name | Description | Arguments |
|---|---|---|
goTo() |
Requests a change to the named step. Emits a cancelable wa-before-step-change; if not canceled, updates
active, emits wa-step-change, and announces the new position to assistive technology. No-ops silently if the
step doesn't exist, is disabled, or (in linear mode) isn't reachable yet. |
name: string
|
next() |
Advances to the step after the active one, if any. | |
previous() |
Goes back to the step before the active one, if any. |
Events
Learn more about events.
| Name | Description |
|---|---|
detail |
|
wa-before-step-change |
Emitted before the active step changes. Calling event.preventDefault() prevents the change, to guard against invalid or unsaved data. |
wa-step-change |
Emitted after the active step changes. |
CSS Custom Properties
Learn more about CSS custom properties.
| Name | Description |
|---|---|
--connector-color |
The color of the connector line after a step that isn't completed.
Default
var(--wa-color-neutral-fill-normal)
|
--connector-color-active |
The color of the connector line after a completed step. Unset by default, so the line takes the completed marker's fill and follows its
variant. |
--connector-gap |
The gap between a marker's edge and the connector line, on both sides. Kept clear of the marker geometrically, so it holds even if a marker's background is transparent.
Default
0.35em
|
--connector-width |
The thickness of the connector line, in either orientation.
Default
var(--wa-border-width-m)
|
--gap |
The space between steps.
Default
var(--wa-space-l)
|
--marker-size |
The size of each step's marker.
Default
2em
|
Custom States
Learn more about custom states.
| Name | Description | CSS selector |
|---|---|---|
completed |
Applied when every step is completed. |
:state(completed)
|
loading |
Applied when at least one step is loading. |
:state(loading)
|
stacked |
Applied while the steps are laid out vertically, whether by orientation="vertical" or because an auto stepper is too narrow to give each step room. |
:state(stacked)
|
CSS Parts
Learn more about CSS parts.
| Name | Description | CSS selector |
|---|---|---|
stepper |
The component's outer wrapper. A <nav> landmark when the stepper is clickable, since its steps are then controls you can navigate with; otherwise a labeled role="group", since a display-only stepper has nothing to navigate. |
::part(stepper)
|
steps |
The <ol> that lays out the steps. |
::part(steps)
|
summary |
Visually hidden "Step X of Y" text that tells assistive technology where the active step sits. |
::part(summary)
|
Dependencies
This component automatically imports the following elements. Sub-dependencies, if any exist, will also be included in this list.
SSR
Learn more about Server-Side Rendering (SSR).
During SSR, <wa-stepper> can't access its children to determine which step is active. To render the correct step, also set the active attribute on the matching <wa-step>. Step numbers appear once the stepper hydrates.