Stepper

Linear with validation

The header is an <ol> of buttons. Each <section> after it is the panel of the step in the same position. With data-linear a user cannot jump ahead, and with data-validate the fields of the current panel must pass before Next moves on. The last Next fires tsunami:stepcomplete. The last panel here is a review, filled from a tsunami:stepchange listener.

Create your account

We send the receipt here.

Choose a plan

Review

Step 1 of 3.

Vertical, with an optional step

data-orientation="vertical" stacks the steps (under 40rem they always stack). A panel with data-optional is not validated, so the user can move past it empty. Without data-linear the header steps are free to click, but going forward still validates the current panel.

Company

Branding

Skip this step if you like.

Billing

Free navigation and the API

With neither data-linear nor data-validate any step can be opened from the header. Move it from script with tsunami.stepper.

Step one

Free navigation: click any step.

Step two

Nothing is validated here.

Step three

The last one.

Behavior

JS sets data-state (done, current or upcoming) on each step button from the current step, and aria-current="step" on the current one. It shows only the current panel and gives each panel role="group", labelled by its step. The first step is current unless the markup marks another with data-state="current". Moving with a button or the API moves focus to the panel heading, or to its first field when there is no heading. Going back never validates. Pressing Enter in a field works as Next, unless the panel has a submit button.

API

Lives in js/stepper.js. It uses event delegation, so steppers added later work too. Each function takes the stepper or any element inside it, or a selector.

Methods

FunctionArgumentsDescription
tsunami.stepper.go(el, index)index: number from 0Opens a step. Going forward validates first (every panel on the way when linear). Returns false if blocked or out of range.
tsunami.stepper.next(el)Next step. On the last step it validates and fires tsunami:stepcomplete.
tsunami.stepper.prev(el)Previous step. Never validates.
tsunami.stepper.index(el)The current step number, from 0.

Events

Both fire on the stepper and bubble.

EventDetailDescription
tsunami:stepchange{ index, step, panel }After a step opens. step is its header <li>.
tsunami:stepcomplete{ index }Next on the last step, once its fields are valid.

Keyboard

KeyContextDescription
Tab / Shift+TabheaderSteps are buttons. Disabled steps are skipped.
Arrow keysheaderMove focus between enabled steps, wrapping. They do not open one.
Home / EndheaderFocus the first / last enabled step.
Enter / SpaceheaderOpen the focused step.
Enterfield in a panelSame as Next, unless the panel has a submit button.

Attributes

Attribute / elementValuesDescription
.stepperdivWraps the <ol> and the panels
> ol > li > buttontype="button"A step. Holds a span with strong (label) and an optional small (description).
> sectionone per step, in orderA panel. Put a heading first and a footer with the buttons.
data-statedone · current · upcomingOn a step button. Set by JS. In markup, current picks the first step.
data-linearpresent / absentOn the stepper: steps after the current one are disabled (aria-disabled).
data-validatepresent / absentOn the stepper: Next and forward jumps run reportValidity() on the current panel's fields.
data-optionalpresent / absentOn a panel: not validated.
data-orientationverticalOn the stepper: stack the steps. Under 40rem it is always vertical.
data-next · data-prevon a button in a panelNext (or finish on the last panel) and Back.