Components

Stepper

The linear progress header of a multi-step flow: numbered pills joined by 40x2 dividers, one label per step. Built for the connection setup wizard (Set up credentials → Set up accounts) and any other sequence where the merchant needs to know where they are and what is left. Four step states and three orientations, all straight from the Figma. Purely display — it reports progress, it does not navigate.

Updated Aug 7, 2026 by Juan Pablo Turina

Anatomy

A flex row of steps separated by dividers. Each step pairs an indicator (the BadgeNumber atom, or a filled CheckCircle once complete) with its label. The current step is the only one in bold, so the eye lands on it first.

  1. Set up credentials
  2. 2Set up costs
  3. 3Set up accounts
  1. 1
    Container

    flex items-center justify-center gap-2 (or flex-col gap-4 in the mobile orientation).

  2. 2
    Indicator

    BadgeNumber (h-5 min-w-5 rounded-full px-1 text-xs) carrying the step number. Swapped for a size-5 filled CheckCircle in primary once the step is complete.

  3. 3
    Label

    text-sm. Bold with leading-none on the current step, regular everywhere else. Muted at 60% opacity when disabled.

  4. 4
    Divider

    h-0.5 w-10 between consecutive steps. Turns bg-primary once the step behind it is complete, so the filled run of line shows the ground already covered; bg-border otherwise. Absent in the mobile orientation.

Step states

Current

Where the merchant is right now. Primary BadgeNumber plus the only bold label in the row — the single strongest signal in the component.

  1. 1Set up credentials
  2. 2Set up accounts
<Stepper steps={["Set up credentials", "Set up accounts"]} current={0} />
Complete

Already done. The badge is replaced by a filled CheckCircle in primary — the number is no longer useful once the step is behind you. Label stays regular.

  1. Set up credentials
  2. 2Set up accounts
<Stepper steps={["Set up credentials", "Set up accounts"]} current={1} />
Active

Ahead of the current step and reachable. Secondary BadgeNumber, regular label at full contrast. This is the default for everything after the current step.

  1. 1Set up credentials
  2. 2Set up costs
  3. 3Set up accounts
<Stepper steps={["Set up credentials", "Set up costs", "Set up accounts"]} current={0} />
Disabled

Not reachable yet (a step gated by an earlier choice). Secondary BadgeNumber with the number and label muted at 60% opacity. Pin it with status on the step object — it is never derived from current.

  1. 1Set up credentials
  2. 2Set up costs
  3. 3Set up accounts
<Stepper
  steps={[
    "Set up credentials",
    { label: "Set up costs", status: "disabled" },
    "Set up accounts",
  ]}
  current={0}
/>

Orientations

Careful with the names: they come from the Figma and they describe how each STEP lays out, not the direction the stepper runs. Only mobile actually stacks the flow.

Horizontal (default)

Steps in a row, each badge beside its label. What the setup wizard uses.

  1. Set up credentials
  2. 2Set up costs
  3. 3Set up accounts
<Stepper steps={steps} current={1} />
Vertical

Steps still run left to right, but each badge sits above its label, centered. Useful when labels are long and you want a narrower row.

  1. Set up credentials
  2. 2Set up costs
  3. 3Set up accounts
<Stepper steps={steps} current={1} orientation="vertical" />
Mobile

Steps stacked in a column with gap-4 and no dividers. For narrow viewports where a row would wrap.

  1. Set up credentials
  2. 2Set up costs
  3. 3Set up accounts
<Stepper steps={steps} current={1} orientation="mobile" />

Import

Copy this import line at the top of the file where you compose this atom.

Stepper is a pure display atom — no state, no callbacks. Drive it with current from whatever owns the wizard step, and pin status per step only when you need disabled.
import { Stepper } from "@/components/ui/stepper";

Props

Everything else from the underlying HTML or Radix primitive is forwarded via ...props.

Stepper

PropTypeDefaultDescription
steps(string | StepperStep)[] (required)Steps in order. Pass plain labels for the common case, or objects when a step needs a pinned status.
currentnumber0Zero-based index of the current step. Everything before it reads as complete, everything after as active.
orientation"horizontal" | "vertical" | "mobile""horizontal"How each step lays out. These are the Figma's names — only mobile stacks the flow into a column.
classNamestringExtra classes on the <ol> container.

StepperStep

PropTypeDefaultDescription
labelstring (required)Step name shown next to (or under) the indicator.
status"complete" | "current" | "active" | "disabled"Overrides the status derived from current. Required to mark a step disabled — that state is never derived.

Related

Cross-links to atoms and patterns you may reach for next.

  • BadgeShips BadgeNumber, the pill the Stepper uses as its indicator. Same h-5 / rounded-full / text-xs anatomy.
  • SeparatorThe general-purpose divider. The Stepper draws its own 40x2 connector instead, so it can sit inline between steps.
  • ProgressUse this instead when progress is continuous (a percentage) rather than a set of named steps.