Stepper
A multi-step progress indicator with horizontal and vertical orientations. Auto-derives step status from activeStep with accessible ARIA roles — copy it into your project and own it completely.
Horizontal (Default)
With Descriptions
Create your account
Set up your profile
Confirm details
Vertical
Prominent Variant
The prominent variant turns the Stepper into a primary-navigation surface: the active row gets a primary-soft tint, the active bullet renders a concentric halo plus a filled pulse dot (replacing the step number), and complete-to-next rails render in a primary-line tint. Use it vertically — it's designed for derivation spines and side-column step navigation.
name · public
working on it now
brand-as-person
Locked Step
All Steps Complete
Installation
npx visor add stepperThis copies two files into your project:
components/ui/stepper/stepper.tsx— the componentcomponents/ui/stepper/stepper.module.css— the styles
Usage
import {
Stepper,
StepperItem,
StepperTrigger,
StepperTitle,
StepperSeparator,
} from '@/components/ui/stepper/stepper';
export default function Example() {
return (
<Stepper activeStep={1}>
<StepperItem step={0}>
<StepperTrigger step={0} />
<StepperTitle>Account</StepperTitle>
</StepperItem>
<StepperSeparator complete />
<StepperItem step={1}>
<StepperTrigger step={1} />
<StepperTitle>Profile</StepperTitle>
</StepperItem>
<StepperSeparator />
<StepperItem step={2}>
<StepperTrigger step={2} />
<StepperTitle>Review</StepperTitle>
</StepperItem>
</Stepper>
);
}Choosing a Variant
| Situation | Variant |
|---|---|
| Multi-step form, checkout, onboarding wizard | default |
| Vertical derivation spine, primary side-column navigation | prominent |
| Stepper is a supporting element on a page | default |
| Stepper is the primary surface of a page | prominent |
The prominent variant uses --interactive-primary-soft for the active-row tint and concentric halo, --interactive-primary-bg for the bullet border, pulse dot, and check fill, and a color-mix tint of --interactive-primary-bg at 34% for the complete-to-next rail. All values resolve against the active theme — monochromatic themes (e.g., Blackout) stay restrained while colorful ones get the full pop.
API Reference
StepperProps
| Prop | Type | Default | Description |
|---|---|---|---|
activeStep | number | 0 | Zero-based index of the currently active step. All steps before this index are considered complete. |
orientation | 'horizontal' | 'vertical' | 'horizontal' | Layout direction of the stepper. "vertical" stacks steps top-to-bottom. |
variant | 'default' | 'prominent' | 'default' | Visual treatment. "default" is the standard step indicator for multi-step forms. "prominent" adds a primary-soft active-row tint, a concentric halo, a filled pulse dot in the active bullet, and a primary-tinted complete rail — use it vertically as a primary derivation spine or navigation surface. |
step* | number | — | Zero-based step index passed to StepperItem and StepperTrigger. Used to auto-derive status. |
status | 'complete' | 'active' | 'upcoming' | 'locked' | — | Explicit status override for StepperItem or StepperTrigger. Auto-derived from activeStep if omitted; "locked" is never auto-derived and must be set explicitly. |
complete | boolean | false | Whether the StepperSeparator line renders in its completed style. |
className | string | — | Additional CSS class names to merge onto the element. |
Sub-components
| Component | Element | Purpose |
|---|---|---|
Stepper | <div> | Root container with context provider |
StepperItem | <div> | Step wrapper, auto-derives status from activeStep |
StepperTrigger | <button> | Clickable step indicator circle |
StepperTitle | <div> | Step label |
StepperDescription | <p> | Step description |
StepperSeparator | <div> | Connecting line between steps |
Accessibility
Stepperrenders withrole="group"andaria-label="Progress"to group the steps as a meaningful unit.StepperItemsetsaria-current="step"on the currently active step.StepperTriggeris a<button>element and includes a visually hidden label ("Completed", "Step N", or "Step N, locked") for screen readers.- The check icon in completed triggers and the lock icon in locked triggers both have
aria-hidden="true"since the status is communicated via the button's text content. - Step status (
complete,active,upcoming,locked) is also exposed as adata-statusattribute for custom CSS targeting. - Locked triggers set
aria-disabled="true"andtabIndex={-1}— they are non-interactive and removed from the tab order. TheonClickhandler is suppressed regardless of what is passed. - When steps are clickable (navigating back), ensure
StepperTriggerhas a meaningfulonClickhandler. For read-only steppers, passdisabledortabIndex={-1}to prevent interaction.