Steppers

The stepper breaks a long task into steps: a checkout, an account set-up, a claim, an import. A step list across the top or down the side shows what is done, which step the reader is on and which needs attention; Back and Next move between them. Each step is a step element holding ordinary content — your own fields and forms.

Next checks the fields in the step before it moves on, then asks your page whether it may, and a step that is refused says why. Steps can be taken in order, with each one opening once the ones before it are done, or in any order. On a narrow screen the list becomes “Step 2 of 5” with a progress bar. The keyboard moves along the list, and every step's state is in its name for screen readers.

A checkout

Four steps, taken in order. Next will not leave the delivery step until the required fields are filled in, and the page itself refuses a postcode that does not look like one. The gift message can be passed over. Finish places the order — here, it shows you what would be sent.

ItemQtyPrice
Oak desk lamp1£48.00
Linen notebook, A53£21.00

Your order.

Try Next on the delivery step with the fields empty.
Get the code
<script src="/assets/bmx-components.min.js"></script>

<bmx-stepper id="st-checkout" label="Checkout" style="inline-size: 100%; max-inline-size: 52rem">
  <bmx-step label="Basket" description="2 items">
    <table class="st-table" aria-label="Your basket">
      <thead><tr><th scope="col">Item</th><th scope="col">Qty</th><th scope="col">Price</th></tr></thead>
      <tbody>
        <tr><td>Oak desk lamp</td><td>1</td><td>&pound;48.00</td></tr>
        <tr><td>Linen notebook, A5</td><td>3</td><td>&pound;21.00</td></tr>
      </tbody>
    </table>
  </bmx-step>
  <bmx-step label="Delivery" description="Where it goes">
    <div class="st-fields">
      <bmx-input id="st-name" name="name" label="Full name" required="true" autocomplete="name"></bmx-input>
      <bmx-input id="st-street" name="street" label="Street" required="true" autocomplete="address-line1"></bmx-input>
      <bmx-input id="st-town" name="town" label="Town" required="true" autocomplete="address-level2"></bmx-input>
      <bmx-input id="st-postcode" name="postcode" label="Postcode" required="true" autocomplete="postal-code" description="A UK postcode, such as LS2 7EY"></bmx-input>
    </div>
  </bmx-step>
  <bmx-step label="Gift message" optional>
    <bmx-textarea id="st-gift" name="gift" label="Message on the card" max-length="200" counter="true"></bmx-textarea>
  </bmx-step>
  <bmx-step label="Review">
    <p id="st-review" style="margin: 0">Your order.</p>
  </bmx-step>
</bmx-stepper>

Setting up a workspace, in any order

The list down the side, and the steps in any order. The page marks steps done as their work completes, and flags the one that needs attention — here, a repository whose token has expired. Fix it and the warning clears.

Done: the workspace northgate-ops exists.

The token for github.com/northgate/ops expired on 30 September.

Renew the token

Not on the free plan.

Get the code
<script src="/assets/bmx-components.min.js"></script>

<bmx-stepper id="st-setup" label="Workspace set-up" orientation="vertical" linear="false" value="repo" style="inline-size: 100%; max-inline-size: 52rem">
  <bmx-step label="Create the workspace" value="create" state="done">
    <p style="margin: 0">Done: the workspace <strong>northgate-ops</strong> exists.</p>
  </bmx-step>
  <bmx-step label="Connect a repository" value="repo" state="error" error-text="The access token has expired">
    <div class="column" style="gap: 12px">
      <p style="margin: 0">The token for <code>github.com/northgate/ops</code> expired on 30 September.</p>
      <bmx-button id="st-renew" variant="solid">Renew the token</bmx-button>
    </div>
  </bmx-step>
  <bmx-step label="Invite your team" value="team" optional>
    <bmx-input id="st-invite" label="Email addresses, separated by commas" style="inline-size: min(100%, 26rem)"></bmx-input>
  </bmx-step>
  <bmx-step label="Billing" value="billing" disabled>
    <p style="margin: 0">Not on the free plan.</p>
  </bmx-step>
</bmx-stepper>

An import that reports its progress

No Back or Next here: the page moves the steps itself as the work goes, completing each and opening the next, and stops on the step that fails. Run it, or run it with a bad row to see a step fail.

Run the import Run it with a bad row

Waiting.

Twelve columns found; all are known.

Checking 4,812 rows.

Saved: 4,812 customers.

Get the code
<script src="/assets/bmx-components.min.js"></script>

<bmx-stepper id="st-import" label="Import progress" hide-controls style="inline-size: 100%; max-inline-size: 52rem">
  <bmx-step label="Upload" value="upload"><p style="margin: 0" id="st-import-upload">Waiting.</p></bmx-step>
  <bmx-step label="Check the columns" value="columns"><p style="margin: 0">Twelve columns found; all are known.</p></bmx-step>
  <bmx-step label="Check the rows" value="rows"><p style="margin: 0" id="st-import-rows">Checking 4,812 rows.</p></bmx-step>
  <bmx-step label="Save" value="save"><p style="margin: 0">Saved: 4,812 customers.</p></bmx-step>
</bmx-stepper>

On a phone

In a narrow space the list gives way to “Step 2 of 5” with the step's name and a progress bar, so the content keeps the room. This is the same element in a column the width of a phone.

A cracked screen, 2 October.

Add a photo of the damage.

For the payment.

Confirm the claim is true.

Send the claim.

Get the code
<script src="/assets/bmx-components.min.js"></script>

<bmx-stepper label="Claim" value="photos">
  <bmx-step label="What happened" value="what" state="done"><p style="margin: 0">A cracked screen, 2 October.</p></bmx-step>
  <bmx-step label="Photos" value="photos"><p style="margin: 0">Add a photo of the damage.</p></bmx-step>
  <bmx-step label="Your bank details" value="bank"><p style="margin: 0">For the payment.</p></bmx-step>
  <bmx-step label="Declaration" value="declare"><p style="margin: 0">Confirm the claim is true.</p></bmx-step>
  <bmx-step label="Send" value="send"><p style="margin: 0">Send the claim.</p></bmx-step>
</bmx-stepper>