# Steps

> A React stepper for checkouts, onboarding and KYC: circles, bars or dots, with complete, error and loading states and a phone header.

- Type: React component (Navigation)
- Access: Pro (the source needs a Wingo UI Pro plan, see https://wingo-ui.com/pricing)
- Version: 1.0.0
- Install: `npx wingo-ui@latest add steps`
- Docs: https://wingo-ui.com/components/steps

## Interaction

Move forward and the connectors fill one after another on a smooth spring, the new current marker pops and the check draws itself in. Click a completed step to go back to it (or any step with clickable="all"). With the keyboard, Tab reaches each clickable step, Left / Right (Up / Down when vertical) move between them and Home / End jump to the first and last. Below 640px a horizontal stepper turns into a compact header: "Step 2 of 4", the step title, what comes next and a progress bar. Dots variant: tap or click a dot to jump (with clickable steps). Clickable markers and dots get a 44px hit area on touch.

## Installation

```bash
npx wingo-ui@latest add steps
```

Pro item: run `npx wingo-ui@latest login` once with a Pro account. The CLI adds the files, their dependencies and a version record for updates.

With shadcn: `npx shadcn@latest add @wingo-ui/steps` (needs the @wingo-ui registry with your API key in components.json)

Files:

- `components/ui/steps.tsx`

npm dependencies: `npm i motion`

Wingo UI dependencies (installed automatically):

- [Spinner](https://wingo-ui.com/components/spinner) ([Markdown](https://wingo-ui.com/components/spinner.md))
- [useControllableState](https://wingo-ui.com/components/use-controllable-state) ([Markdown](https://wingo-ui.com/components/use-controllable-state.md))
- [Motion presets](https://wingo-ui.com/components/motion) ([Markdown](https://wingo-ui.com/components/motion.md))
- [Navigation](https://wingo-ui.com/components/navigation) ([Markdown](https://wingo-ui.com/components/navigation.md))
- [Tones](https://wingo-ui.com/components/tones) ([Markdown](https://wingo-ui.com/components/tones.md))
- [UIProvider](https://wingo-ui.com/components/ui-config) ([Markdown](https://wingo-ui.com/components/ui-config.md))

## Usage

```tsx
import { useState } from "react"
import { Steps, type StepItem } from "@/components/ui/steps"

const STEPS: StepItem[] = [
  { id: "cart", title: "Cart", description: "3 items" },
  { id: "shipping", title: "Shipping", description: "FedEx" },
  { id: "payment", title: "Payment" },
  { id: "review", title: "Review" },
]

export function CheckoutSteps() {
  const [step, setStep] = useState("shipping")
  return (
    <Steps
      steps={STEPS}
      value={step}
      onValueChange={setStep}
    />
  )
}
```

## Props

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `steps` | `StepItem[]` |  | { id: string; title: ReactNode; description?: ReactNode; icon?: ReactNode; status?: StepStatus; optional?: boolean; disabled?: boolean; href?: string }. status overrides the derived one (complete before value, current at it, upcoming after); errors and loading are always explicit. |
| `value?` | `string` |  | The current step id, controlled. An id that is not among the steps leaves every step upcoming. |
| `defaultValue?` | `string` | `""` | The starting step id while uncontrolled. Empty starts on the first step; an id that is not among the steps leaves them all upcoming. The playground takes cart, shipping, payment or review. |
| `onValueChange?` | `(id: string, step: StepItem) => void` |  | Fires when a clickable step is clicked. |
| `orientation?` | `"horizontal" \| "vertical"` | `"horizontal"` | Vertical stacks the steps with their descriptions beside a column of markers; it works at any width. |
| `variant?` | `"circles" \| "bars" \| "dots"` | `"circles"` | circles: numbered markers joined by connectors (the form-wizard look). bars: one segment per step with the title under it (checkout). dots: small dots, the current one widened (onboarding). |
| `size?` | `"sm" \| "md" \| "lg"` | `"md"` | Markers 24 / 28 / 32px, titles 13 / 14 / 15px, descriptions 12 / 13 / 13px. |
| `tone?` | `"neutral" \| "brand" \| "success" \| "warning" \| "danger" \| "info"` | `"neutral"` | Paints the current marker, the tint of completed markers and the connector fill. |
| `color?` | `string` | `""` | Any CSS color. Replaces the tone; text on the current marker turns black or white by lightness. |
| `labelPlacement?` | `"bottom" \| "end"` | `"bottom"` | Horizontal circles: titles centered under the markers (clamped to two lines), or beside them with the connector after the text. |
| `clickable?` | `"none" \| "completed" \| "all"` | `"completed"` | Which steps are buttons: none, the ones already done (plus the current one and ones marked with an error), or every enabled step. Disabled steps never are. |
| `connector?` | `"solid" \| "dashed"` | `"solid"` | dashed draws the connectors (and bar segments) still ahead as dashes. |
| `mobileVariant?` | `"compact" \| "same"` | `"compact"` | Below 640px a horizontal circles or bars stepper becomes the compact header ("Step 2 of 5", title, next step, progress bar). Pure CSS: both are rendered, so the server HTML is right on a phone. |
| `compact?` | `boolean` | `false` | Always shows the compact header, at every width: phone screen headers, narrow cards, sheets. Horizontal circles and bars only (vertical and dots keep their layout). |
| `showDescription?` | `boolean` | `true` | Descriptions under the titles. Vertical steppers always show them. |
| `linkComponent?` | `(props: LinkComponentProps) => ReactNode` |  | The link component for href steps (a router Link, or "a"). Default: the one set by LinkProvider, a plain <a> without one. |
| `labels?` | `{ progress?: string; step?: (position: number, count: number) => string; next?: (title: ReactNode) => ReactNode; complete?: string; current?: string; error?: string; loading?: string; optional?: string }` |  | Text for screen readers and the compact header. Defaults: "Progress", "Step 2 of 5", "Next: …", "Completed", "Current step", "Needs attention", "In progress", "Optional". |
| `classNames?` | `Partial<Record<"list" \| "item" \| "trigger" \| "marker" \| "title" \| "description" \| "connector" \| "compact", string>>` |  | Extra classes for the inner parts. |
| `className?` | `string` |  | Extra classes for the root, merged last. |

## Parts

### StepItem (type)

One step: id, title, description, icon (replaces the number), status (overrides the derived one; error and loading are always set here), optional, disabled and href (renders the step as a link).

### StepStatus (type)

"complete" | "current" | "upcoming" | "error" | "loading".

## Examples

- **Vertical with descriptions**: Icons stand in for the numbers; an optional step says so.
- **Loading and error**: The identity check spins for 1.4s, then fails. Retry and it passes.
- **Bars**: One segment per step, every step clickable. The checkout look.
- **Dots**: For onboarding carousels: the current dot widens on a spring.
- **Linked steps**: Steps with href render as links through the app's router, with aria-current="step".
- **Sizes and tones**: sm neutral, md brand, lg success with dashed connectors ahead.
- **Phone header**: compact: "Step 2 of 4", the title, what comes next and a bar.

## See also

- [Form Wizard](https://wingo-ui.com/components/form-wizard) ([Markdown](https://wingo-ui.com/components/form-wizard.md))
- [Checkout steps](https://wingo-ui.com/components/checkout-steps) ([Markdown](https://wingo-ui.com/components/checkout-steps.md))
- [Step Player](https://wingo-ui.com/components/step-player) ([Markdown](https://wingo-ui.com/components/step-player.md))
- [Progress](https://wingo-ui.com/components/progress) ([Markdown](https://wingo-ui.com/components/progress.md))
- [Navigation](https://wingo-ui.com/components/navigation) ([Markdown](https://wingo-ui.com/components/navigation.md))
- [Tabs](https://wingo-ui.com/components/tabs) ([Markdown](https://wingo-ui.com/components/tabs.md))

---

Canonical: https://wingo-ui.com/components/steps
More components: https://wingo-ui.com/components · Index for agents: https://wingo-ui.com/llms.txt
