Multi-step progress indicator with completed/active/pending/error/loading states, horizontal or vertical orientation, and full keyboard navigation.
Compound API (a stepper and its steps: PixelStepper.Step, PixelStepperStep in Vue, pxl-stepper-step in Angular) keeps step content declarative and easy to reorder.
Per-step states (completed, active, pending, error, loading) with tone-mapped indicators and connectors.
Horizontal or vertical orientation with roving focus, Arrow/Home/End keys, and Enter/Space activation.
Optional step clicks (onStepClick, @step-click in Vue, clickable + (stepClick) in Angular) with allowNextStepsSelect gate so future steps stay locked until allowed.
Surface-aware (pixel/linear) and size-aware (sm/md/lg), inheriting kit-wide tokens and focus rings.
Status
stable
Category
navigation
Since
v1.9.0
API
import { PixelStepper } from '@pxlkit/ui-kit';
PixelStepper
Prop
Type
Default
Description
active* (required)
number
—
Index of the current step, from 0.
onStepClick
(idx: number) => void
—
Called with the index of a step that is clicked, or activated with Enter or Space. With it, the steps up to the active one — every step with allowNextStepsSelect — are clickable and in the tab order.
orientation
'horizontal' | 'vertical'
'horizontal'
Steps in a row or a column; also the arrow keys that move between them.
allowNextStepsSelect
boolean
false
With onStepClick, makes the steps after the active one clickable too.
size
'sm' | 'md' | 'lg'
'md'
Size of the indicators and labels.
surface
'pixel' | 'linear'
—
Surface override; defaults to the nearest provider.
ariaLabel
string
'Progress steps'
Accessible name for the steps landmark. Defaults to "Progress steps".
children* (required)
React.ReactNode
—
The steps (PixelStepper.Step).
Also takes the native attributes and event handlers of <div> (HTMLAttributes<HTMLDivElement>).
ref points to <div>.
PixelStepper.Step
Prop
Type
Default
Description
label* (required)
string
—
Label under (or beside) the indicator.
description
string
—
Smaller text below the label.
icon
React.ReactNode
—
Custom icon in the indicator, shown while the step is neither completed nor in error.
loading
boolean
false
Shows a spinner in the indicator.
completed
boolean
false
Marks the step done, with a check mark.
error
boolean
false
Marks the step failed, with a cross; wins over completed.
Also takes the native attributes and event handlers of <div> (HTMLAttributes<HTMLDivElement>), except children.
ref points to <div>.
Accessibility
WCAG target: 2.1 AA
progress-steps
The root renders role="group" with a configurable ariaLabel (defaults to "Progress steps"). A clickable step is role="button", named by its position ("Step N of M"), its label and its state (current/completed/error) and described by its description. A step that is not clickable (no step click handling, or a future step when allowNextStepsSelect is false) has no role and stays out of the tab sequence; since ARIA does not let an element without a role take a name, it reads its position and state as visually hidden text around its label. The active step is marked with aria-current="step". Indicators and connectors are aria-hidden so screen readers announce only the step label and state.
Keyboard
Key
Action
When
Tab
Moves focus into/out of the stepper; only clickable steps participate in the tab sequence.
—
ArrowRight
Focuses the next clickable step.
orientation="horizontal"
ArrowLeft
Focuses the previous clickable step.
orientation="horizontal"
ArrowDown
Focuses the next clickable step.
orientation="vertical"
ArrowUp
Focuses the previous clickable step.
orientation="vertical"
Home
Focuses the first clickable step.
—
End
Focuses the last clickable step.
—
Enter
Activates the focused step (when clickable).
—
Space
Activates the focused step (when clickable).
—
Usage
import { PixelStepper } from '@pxlkit/ui-kit';
export function Default() {
return (
<PixelStepper active={1}>
<PixelStepper.Step label="Account" description="Create your account" />
<PixelStepper.Step label="Profile" description="Add some details" />
<PixelStepper.Step label="Confirm" description="Review and submit" />
</PixelStepper>
);
}
Examples
Default
import { PixelStepper } from '@pxlkit/ui-kit';
export function Default() {
return (
<PixelStepper active={1}>
<PixelStepper.Step label="Account" description="Create your account" />
<PixelStepper.Step label="Profile" description="Add some details" />
<PixelStepper.Step label="Confirm" description="Review and submit" />
</PixelStepper>
);
}