---
title: Stepper
description: Step indicator for multi-step flows
visibility: guest
draft: false
---

# Stepper

The `<x-wirekit::stepper>` component shows progress through a multi-step flow. Each step is automatically styled based on its position relative to the current step: completed (filled), current (outlined), or upcoming (muted).

## Usage

:::preview{title="Horizontal Stepper" wide}
<x-wirekit::stepper :steps="['Cart', 'Shipping', 'Payment', 'Confirm']" :current="2" />
:::

Steps before `current` show a checkmark. The current step is outlined with the accent color. Upcoming steps are muted.

## With Descriptions

:::preview{title="Stepper with Descriptions" wide}
<x-wirekit::stepper :steps="[
    ['label' => 'Cart', 'description' => 'Review items'],
    ['label' => 'Shipping', 'description' => 'Address details'],
    ['label' => 'Payment', 'description' => 'Card info'],
    ['label' => 'Confirm', 'description' => 'Final review'],
]" :current="3" />
:::

## Vertical Orientation

:::preview{title="Vertical Stepper"}
<x-wirekit::stepper orientation="vertical" :steps="[
    ['label' => 'Account', 'description' => 'Create your account'],
    ['label' => 'Profile', 'description' => 'Tell us about you'],
    ['label' => 'Plan', 'description' => 'Choose a plan'],
]" :current="2" />
:::

## Props

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `steps` | `array` | `[]` | Array of step labels (strings) or `['label' => .., 'description' => ..]` arrays |
| `current` | `int` | `1` | 1-based index of the current step |
| `orientation` | `string` | `'horizontal'` | `'horizontal'` or `'vertical'` |
| `scope` | `string\|null` | `null` | Scoped personalization key |

## Accessibility

- Outer `<ol aria-label="Progress">` — semantic ordered list
- Current step marked with `aria-current="step"` on its `<li>`
- Completed steps include a visually hidden "Completed:" label for screen readers
- Step numbers and icons are `aria-hidden="true"` (state conveyed via `aria-current`)
- Connector lines are `aria-hidden="true"` (decorative)

## Keyboard Interaction

The stepper is a **purely presentational** progress indicator — a semantic `<ol>` of steps with no focusable or clickable controls of its own. There is no step to activate: the current position is conveyed with `aria-current`, and the numbers, icons and connector lines are `aria-hidden`. Nothing to tab to, nothing to press.

If your flow needs the user to *navigate* between steps, use [`<x-wirekit::wizard>`](/components/wizard): it holds the step, gates advancing on a per-step condition, announces the change to a screen reader, and renders this stepper inside itself. The stepper reflects state either way — it does not own the navigation, and the wizard does not change that.

Driving `current` from your own controls stays perfectly valid and is the right answer when the flow's state already lives somewhere else.

## Pitfalls

- **The stepper does not make steps clickable.** It shows where the user is; it is not a nav. If you want jump-back, add your own buttons/links and update `current` — and only allow non-linear jumps when the flow genuinely is non-linear (a clickable jump-back in a checkout undermines progress validation). [`<x-wirekit::wizard>`](/components/wizard) keeps the same position: it adds Back and Next around the stepper and leaves the indicator presentational.

## Design Tokens

| Token | Used for |
| --- | --- |
| `--font-wk-heading-weight` | Step number font weight |
| `--text-wk-xs` / `--text-wk-sm` | Step number / label font size |
| `--color-wk-text` | Active + completed step label |
| `--color-wk-text-muted` | Pending step label |
| `--color-wk-accent` | Active + completed circle background |
| `--color-wk-accent-fg` | Active + completed circle text |
| `--color-wk-bg` | Pending circle background |
| `--color-wk-border` | Pending circle border + connector line |
| `--border-wk-width` | Circle + connector border width |
| `--padding-wk-x-sm` / `--padding-wk-y-xs` / `--padding-wk-y-md` | Step item padding |
| `--transition-wk-duration` | State transition |

## Customization

### Accent Color

The step indicator circles use `--color-wk-accent` for the current and completed states. Override it to match your brand:

:::preview{title="Green Accent Stepper"}
<x-wirekit::stepper :steps="['Cart', 'Shipping', 'Payment', 'Confirm']" :current="3" style="--color-wk-accent: #15803d; --color-wk-accent-fg: #fff; max-width: 32rem; margin-inline: auto;" />
:::

:::preview{title="Purple Accent Stepper"}
<x-wirekit::stepper :steps="['Cart', 'Shipping', 'Payment', 'Confirm']" :current="2" style="--color-wk-accent: #9333ea; --color-wk-accent-fg: #fff; max-width: 32rem; margin-inline: auto;" />
:::

### Completed Step at End

:::preview{title="All Steps Completed"}
<x-wirekit::stepper :steps="['Cart', 'Shipping', 'Payment', 'Confirm']" :current="5" style="max-width: 32rem; margin-inline: auto;" />
:::

### Vertical with Custom Color

:::preview{title="Vertical Stepper — Blue Accent"}
<x-wirekit::stepper orientation="vertical" :steps="[
    ['label' => 'Order Placed', 'description' => 'April 1, 2026'],
    ['label' => 'Processing', 'description' => 'April 2, 2026'],
    ['label' => 'Shipped', 'description' => 'Estimated April 5'],
    ['label' => 'Delivered', 'description' => 'Pending'],
]" :current="3" style="--color-wk-accent: #2563eb; --color-wk-accent-fg: #fff; max-width: 32rem; margin-inline: auto;" />
:::

### Design Tokens

| Element | Token |
| --- | --- |
| Circle completed bg | `--color-wk-accent` |
| Circle completed text | `--color-wk-accent-fg` |
| Circle current border | `--color-wk-accent` |
| Circle current text | `--color-wk-accent` |
| Circle upcoming border | `--color-wk-border` |
| Circle upcoming text | `--color-wk-text-muted` |
| Connector line | `--color-wk-border` |
| Label text | `--color-wk-text` |
| Description text | `--color-wk-text-muted` |
| Circle size | `w-8 h-8` (2rem) — override via scoped personalization |
| Font weight (circle) | `--font-wk-heading-weight` |
| Transition | `--transition-wk-duration` |

To change the circle size globally, use scoped personalization:

```php
// config/wirekit.php
'personalizations' => [
    'stepper' => [
        'my-scope' => [
            'circle' => 'w-10 h-10 text-base', // larger circles
        ],
    ],
],
```

```blade
<x-wirekit::stepper scope="my-scope" :steps="['A', 'B', 'C']" :current="2" />
```

## Config Defaults

The defaults live in `config/wirekit.php` under `components.stepper`. Override them globally:

```php
'components' => [
    'stepper' => ['orientation' => 'vertical'], // default to vertical
],
```

## Further Reading

- [MDN: `aria-current`](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-current) — used with value `"step"` to mark the active step
- [MDN: `<ol>` element](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/ol) — semantic ordered list
- [WAI-ARIA: step indicator patterns](https://www.w3.org/WAI/ARIA/apg/patterns/)
