Skip to content

ComponentsNavigation

Stepper

Shows where the user is in a multi-step flow, such as onboarding, checkout or a setup wizard. Horizontal or vertical, with complete, current, upcoming and error states, optional descriptions and icons, two sizes, and pressable steps for moving back through the flow.

Source
  1. AccountName and email, Completed
  2. 2WorkspaceTeam and URL, Current step
  3. 3BillingPlan and payment, Not started

Installation

pnpm dlx shadcn@latest add @desyne/stepper

The CLI installs dependencies and any other components this one uses.

Usage

tsx
import { Step, Stepper } from "@/components/ui/stepper";
tsx
<Stepper aria-label="Workspace setup" currentStep={1}>
  <Step title="Account" description="Name and email" />
  <Step title="Workspace" description="Team and URL" />
  <Step title="Billing" description="Plan and payment" />
</Stepper>

currentStep is the zero-based index of the active step. Steps before it are complete, the step itself is current, and later steps are upcoming. Set status on a Step to override this, for example to mark a step as error.

When to use

  • Stepper: a flow with a fixed number of ordered steps, where knowing what's left helps the user (onboarding, checkout, import wizards, KYC).
  • Tabs: sections the user can visit in any order.
  • Progress Bar: progress of a task the user isn't driving step by step.
  • Timeline: a record of events that already happened.

Anatomy

tsx
<Stepper>                 {/* <ol>, orientation, size, currentStep */}
  <Step title description>{/* <li>, data-status */}
    {/* indicator: number, check, cross or icon */}
    {/* title + description (a <button> when pressable) */}
    {/* connector to the next step */}
    {/* children: content under the title (vertical only) */}
  </Step>
</Stepper>
PartRendersNotes
Stepper<ol>Ordered list. Pass aria-label to name the flow. Provides orientation, size and currentStep to its steps.
Step<li>Sets data-status and aria-current="step" on the current step.
Indicator<span>The step number (1-based, unpadded), a check when complete, a cross on error, or your icon.
TriggerReact Aria Button or <div>A button when onStepChange is set and the step can be reached; otherwise plain text.
Connector<span>Line to the next step. Brand-colored once the step is complete. Not rendered after the last step.
Content<div>children of a Step, shown under the title in vertical steppers.

Examples

Vertical

orientation="vertical" stacks steps with the connector running down the left. Pass children to a Step to show content under its title, such as the active step's form.

  1. Verify your domainAdd a TXT record to acme.com, Completed
  2. 2Configure SSOConnect Okta, Google or any SAML 2.0 provider, Current step

    Paste the metadata URL from your identity provider, then test the connection with your own account.

  3. 3Invite your teamMembers on acme.com can join automatically, Not started

Pressable steps

With onStepChange, reachable steps render as buttons and pressing one calls the handler with its index. By default (isLinear), only steps up to currentStep are pressable, so users can go back but not skip ahead. Set isLinear={false} to allow any step.

  1. 4Review, Not started

Press a completed step to go back to it. Later steps unlock as you continue.

Error state and icons

status="error" shows a cross and turns the title red. Use description to say what went wrong. icon replaces the number (and the check or cross) with your own glyph.

  1. Build1m 12s, Completed
  2. UploadBundle exceeds 50 MB, Error
  3. Release, Not started
  1. Upload file, Completed
  2. Map columns2 unmatched, Error
  3. 3Import, Not started

Sizes

md (32px indicators) is the default. sm (24px) suits dialogs, sidebars and dense headers.

  1. Details, Completed
  2. 2Documents, Current step
  3. 3Review, Not started
  4. 4Submit, Not started
  1. Details, Completed
  2. 2Documents, Current step
  3. 3Review, Not started
  4. 4Submit, Not started

Accessibility

  • The stepper is an <ol>, so screen readers announce the number of steps and each step's position. Give it an aria-label that names the flow, e.g. "Checkout".
  • The current step gets aria-current="step" (on its button when pressable, otherwise on the <li>).
  • Each step includes visually hidden status text ("Completed", "Current step", "Not started", "Error"), so status isn't conveyed by color or icon alone.
  • Pressable steps are React Aria buttons: they work with mouse, touch and keyboard (Tab, then Enter or Space) and show a focus ring on keyboard focus. Unreachable steps aren't buttons, so they aren't in the tab order.
  • The connector and indicator glyphs are decorative.
  • A stepper doesn't move focus. When the step changes, move focus to the new step's heading or first field yourself.

Styling

Data attributes

AttributeOnValues
data-slot="stepper"StepperAlways
data-orientationStepperhorizontal · vertical
data-slot="step"StepAlways
data-statusStepcomplete · current · upcoming · error
data-slot="step-indicator"IndicatorAlways
data-slot="step-trigger"Pressable triggerWhen pressable
data-slot="step-title" / step-descriptionTextAlways / with description
data-slot="step-connector"ConnectorAll but the last step
data-slot="step-content"ChildrenVertical, with children

Step sets the group/step group, so you can style its children by status:

tsx
<Step className="group-data-[status=error]/step:..." title="Upload" />

API Reference

Stepper

Prop

Type

Also accepts every prop of <ol>.

Step

Prop

Type

Also accepts every prop of <li>.