Skip to contentAsheeUIAsheeUI

Stepper

The reader's progress through a sequence of steps, stated as a list.

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.

Usage

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.

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.

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.

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

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 Enter and Space, and the labels name them. Without it there are no controls at all, which is the honest markup for progress text.