Stepper reports where a reader is in a sequence, a checkout, an onboarding flow, a wizard, and
nothing more. It is not a field: its steps are read rather than filled in, so it states only how
they are arranged and how dense they are. Each step reports its own state as complete, current or
upcoming, in colour and in words, so where the reader is does not depend on seeing a marker.

```tsx demo="forms/stepper-preview"
```

## Usage

```tsx
import { Stepper } from "@asheeui/web";

<Stepper
  currentStep={1}
  steps={[
    { key: "cart", label: "Cart" },
    { key: "delivery", label: "Delivery", description: "Where it goes" },
    { key: "payment", label: "Payment" },
  ]}
/>
```

`currentStep` is a zero-based index: every step before it is complete, that step is current, and
every step after it is upcoming. A step is a `key`, a `label` and an optional `description`. As
written above it only reports progress, nothing in it can be pressed, because `onStepChange` was
not given. For the form the steps belong to, see [Building a form](/guides/building-a-form).

## Making the steps pressable

The presence of `onStepChange` is the switch: give it a handler and every step except the current
one becomes a button, so a reader can go back and, if the page allows it, skip ahead. The stepper
reports the index a reader asked for; what that means, a route, a schema check, a refusal, is
the page's decision.

```tsx demo="forms/stepper-changing"
```

The current step is never a button: pressing where you already are would do nothing, and a control
that does nothing is worse than no control. A stepper used this way usually has a page control
beside it for the ordinary back and next movements, because those are the steps a reader takes
most.

## Orientation

`orientation` decides how the steps are laid out. The default, `responsive`, is a column on a
narrow screen and a row from the `md` breakpoint, which is the shape a checkout summary needs
without a media query at every use. `horizontal` is a row at every width, for two or three short
steps; `vertical` is a column at every width, for a long sequence or a sidebar.

```tsx demo="forms/stepper-orientations"
```

`size` sets the scale of the markers *and* their labels, `sm`, `md` or `lg`, and
`showDescriptions` (`true` by default) decides whether each step's description sits under its
label. A rule is drawn between steps only when they are in a row, so a column states its sequence
through order alone.

## Props

```props Stepper
```

The three settings are registered under `components.stepper`: `orientation` as `responsive`,
`size` as `md` and `showDescriptions` as `true`, so an application can restate them for every
stepper it renders. `steps` and `currentStep` are the component's own inputs and have no default.
`as` defaults to `ol`, which is what states the sequence as a list, replace it only with an
element that keeps the same meaning.

## Accessibility

- The sequence is an ordered list: `ol` by default, with one `li` per step, so the reader is told
  the list's length and their position in it. `label` names the list, which is worth setting on a
  page with more than one.
- The current step's `li` carries `aria-current="step"`, so the answer to "where am I" is an
  attribute rather than a shade of colour.
- Each step's state is also written out, `Completed:`, `Current step:`, `Not started:`, in text
  that is visually hidden, and the marker is `aria-hidden`, so the state is never carried by the
  marker alone. Descriptions are ordinary text, and the rule drawn between steps is `aria-hidden`.
- With `onStepChange`, the reachable steps are real `<button>` elements inside their list items:
  they are in the tab order, they press with <kbd>Enter</kbd> and <kbd>Space</kbd>, and the labels
  name them. Without it there are no controls at all, which is the honest markup for progress text.

## Related

```related tabs, pagination, form
```
