# Stepper

## Overview

The stepper component shows ordered progress through a short sequence of steps such as onboarding, checkout, or form completion.

The component styles a native ordered list inside a `.stepper` container and uses list item state attributes to distinguish complete, current, and upcoming steps.

## When to use

Use a stepper to show the user's position within a short, strictly ordered sequence of named steps.

## When not to use

Do not use a stepper for a long sequence, overall completion without named steps, or freely navigable peer sections; use progress or nav.

## Usage

```html
<div class="stepper">
  <ol aria-label="Account setup progress">
    <li data-step-state="complete">
      <p>Account details</p>
    </li>
    <li aria-current="step">
      <p>Profile setup</p>
    </li>
    <li>
      <p>Review and submit</p>
    </li>
  </ol>
</div>
```

Use this component when the interface needs to show where the user is within a small, linear set of steps.

Use [progress.css](./progress.md) instead when the sequence is too long for a stepper to scan comfortably or when the user only needs overall completion rather than each named step.

Use nav instead when the sections are not strictly sequential or the user can move freely between them.

Each step label should stay short enough to scan quickly without wrapping into long blocks of text.

The current step should use `aria-current="step"` and completed steps should use `data-step-state="complete"` so visual state does not replace semantic structure.

Apply the `.stepper` class to the immediate parent wrapper so the component has an inline-size query container for its stacked layout.

Give the ordered list a descriptive accessible name with `aria-label` or `aria-labelledby` so assistive technologies can announce what progress the list represents.

## Behavior

Covered by [Playwright behavior tests](../../tests/e2e/components.spec.js).

- STP-001: The component uses the ordered list counter for default step numbers rather than requiring explicit numeric content in the markup.
- STP-002: Completed steps replace the number with a check icon and tint the connector line with the success color.
- STP-003: The completed-step check icon color is controlled by `--stepper-complete-icon-color`, which should alias a theme semantic token.
- STP-004: The current step increases emphasis with a stronger label weight and a brand-colored outer ring around the step indicator.
- STP-005: Upcoming steps use a strong surface fill and subtle border track so the completed and current states carry the strongest emphasis.
- STP-006: Comfortable and compact density come from the shared layout theme tokens rather than stepper-specific theme branches.
- STP-007: When the stepper container gets narrow enough, the layout stacks vertically and the connector line shifts from horizontal to vertical.
- STP-008: If the `.stepper` wrapper is omitted, the ordered list will not receive the component styles or container-query-driven stacked layout.
## Accessibility

- Use a native `<ol>` so assistive technologies can announce the total number of steps and the user’s position in the sequence.
- Keep the list's accessible name descriptive, such as `aria-label="Checkout progress"` or `aria-labelledby` pointing to a visible heading.
- Use `aria-current="step"` only on the active step.
- Do not use `aria-label` as a visual state hook on individual steps because that can override the accessible name.
- Keep visible step text meaningful on its own, since the indicator circle is decorative context rather than the primary label.

## Variables

| Variable | Type | Description |
| --- | --- | --- |
| `--stepper-active-color` | `<color>` | Sets the current-step indicator fill and outer ring color; change it when the active step should use a different brand or status accent. |
| `--stepper-color-accent` | `<color>` | Sets --stepper-color-accent so the component can default to shared theme or layout tokens while exposing an overrideable component API. |
| `--stepper-color-text` | `<color>` | Sets --stepper-color-text so the component can default to shared theme or layout tokens while exposing an overrideable component API. |
| `--stepper-color-text-inverse` | `<color>` | Sets --stepper-color-text-inverse so the component can default to shared theme or layout tokens while exposing an overrideable component API. |
| `--stepper-complete-color` | `<color>` | Sets completed-step indicator fills and completed connector lines; change it when finished steps should use a different success treatment. |
| `--stepper-complete-font-size` | `<length>` | Sets the Material Symbols checkmark size for completed steps; change it when the check should feel larger or smaller inside the circle. |
| `--stepper-complete-icon-color` | `<color>` | Sets the checkmark color on completed steps; change it when the completed fill color requires a different contrast pairing. |
| `--stepper-gap` | `<length>` | Sets horizontal spacing between steps and factors into connector length; change it to make wide steppers more compact or more open. |
| `--stepper-icon-font-family` | `Any` | Sets --stepper-icon-font-family so the component can default to shared theme or layout tokens while exposing an overrideable component API. |
| `--stepper-idle-color` | `<color>` | Sets the fill color for future step indicators; change it when inactive steps need more or less visual weight. |
| `--stepper-indicator-font-size` | `<length>` | Sets the number size inside idle and active step indicators; change it when step numbers should scale independently from labels. |
| `--stepper-indicator-size` | `<length>` | Sets the diameter of each step indicator and drives connector positioning; change it when targets or visual hierarchy need larger or smaller circles. |
| `--stepper-label-font-size` | `<length>` | Sets the text size for step labels; change it when step descriptions should be denser or more prominent. |
| `--stepper-line-offset` | `<length>` | Sets the horizontal inset between an indicator and its connector line; change it when connectors should start closer to or farther from circles. |
| `--stepper-line-thickness` | `<length>` | Sets connector line thickness in horizontal and stacked layouts; change it when progress lines need stronger or subtler emphasis. |
| `--stepper-ring-gap` | `<length>` | Sets the gap between the active indicator and its outer ring; change it to tune the current-step halo spacing. |
| `--stepper-ring-size` | `<length>` | Sets the thickness of the active-step outer ring; change it when the current step needs a stronger or lighter halo. |
| `--stepper-space-inline` | `<length>` | Sets --stepper-space-inline so the component can default to shared theme or layout tokens while exposing an overrideable component API. |
| `--stepper-space-stack` | `<length>` | Sets --stepper-space-stack so the component can default to shared theme or layout tokens while exposing an overrideable component API. |
| `--stepper-stack-gap` | `<length>` | Sets vertical spacing between steps in the stacked container layout; change it when narrow steppers need more or less breathing room. |
| `--stepper-track-color` | `<color>` | Sets the connector color for incomplete step paths; change it when remaining progress should appear more or less prominent. |

## Depends On

- `--color-accent`
- `--color-accent-strong`
- `--color-border-subtle`
- `--color-primary`
- `--color-success`
- `--color-text`
- `--color-text-inverse`
- `--font-size`
- `--icon-font-family`
- `--layout-control-min-height`
- `--layout-focus-ring-size`
- `--layout-space-inline`
- `--layout-space-stack`
## Migrating From Unstack

The stepper is not a drop-in replacement for the Unstack stepper because the wrapper and completed-step state hook changed.

Update this Unstack markup:

```html
<ol aria-label="Progress">
  <li aria-label="complete">
    <p>Create Account</p>
  </li>
  <li aria-current="step">
    <p>Personal Information</p>
  </li>
  <li>
    <p>Summary</p>
  </li>
</ol>
```

To this component contract:

```html
<div class="stepper">
  <ol aria-label="Account setup progress">
    <li data-step-state="complete">
      <p>Create Account</p>
    </li>
    <li aria-current="step">
      <p>Personal Information</p>
    </li>
    <li>
      <p>Summary</p>
    </li>
  </ol>
</div>
```

Migration steps:

- Add the `.stepper` wrapper around the ordered list so the container-query stacked layout can activate.
- Replace the generic `aria-label="Progress"` with a descriptive accessible name, such as `aria-label="Account setup progress"` or `aria-labelledby` pointing to a visible heading.
- Replace `aria-label="complete"` on completed steps with `data-step-state="complete"` so visual state does not override the step's accessible name.
- Keep `aria-current="step"` on the current step.
- Include the required color, layout, typography, and icon tokens listed above before using the component.
