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.
| Item | Qty | Price |
|---|---|---|
| Oak desk lamp | 1 | £48.00 |
| Linen notebook, A5 | 3 | £21.00 |
Your order.
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>£48.00</td></tr>
<tr><td>Linen notebook, A5</td><td>3</td><td>£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.
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.
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>