Stepper
hc-stepper shows progress through a multi-step flow. It ships no
JavaScript at all: the server renders the whole indicator on every
step — including the marker content (the step number, or ✓ once a
step completes) — so every state change arrives as markup. The
indicator displays; navigation is the job of the step’s form (see the
multi-step form recipe).
Basic HTML
Section titled “Basic HTML”- Account (completed)
- Profile
- Review
<ol class="hc-stepper"> <li class="hc-stepper__step" data-state="complete"> <span class="hc-stepper__marker" aria-hidden="true">✓</span> <span class="hc-stepper__label">Account <span class="hc-sr-only">(completed)</span></span> </li> <li class="hc-stepper__step" aria-current="step"> <span class="hc-stepper__marker" aria-hidden="true">2</span> <span class="hc-stepper__label">Profile</span> </li> <li class="hc-stepper__step"> <span class="hc-stepper__marker" aria-hidden="true">3</span> <span class="hc-stepper__label">Review</span> </li></ol>States
Section titled “States”| State | Selector | Effect |
|---|---|---|
| Current | [aria-current="step"] | Accent marker (follows data-color), emphasized label. |
| Complete | [data-state="complete"] | Tinted marker; the server renders ✓ as the marker content. |
| Upcoming | (no attribute) | Muted marker and label. |
The server renders the marker content. A number for pending steps,
✓ for completed ones — no CSS content tricks, no client mutation.
Add a visually hidden (completed) suffix to completed labels so the
state is announced; aria-current="step" covers the current one.
Clickable completed steps
Section titled “Clickable completed steps”Render a completed step’s content as a link to its step URL if the flow allows revisiting — the stepper styles it quietly (underline on hover/focus). This is the server’s choice per step; the indicator never invents navigation. Keep the marker outside the link so the column layout holds:
- Account (completed)
- Profile
- Review
<li class="hc-stepper__step" data-state="complete"> <span class="hc-stepper__marker" aria-hidden="true">✓</span> <a href="/checkout/account"> <span class="hc-stepper__label">Account <span class="hc-sr-only">(completed)</span></span> </a></li>data-size="sm" shrinks the markers for dense layouts. Horizontal
only — a vertical orientation is a deliberate non-goal for now.
- Account (completed)
- Profile
- Review
<ol class="hc-stepper" data-size="sm"> <!-- …the same steps… --></ol>htmx usage
Section titled “htmx usage”The server re-renders the whole indicator on every step: the step
form’s response (see the
multi-step form recipe)
simply includes the <ol> again with aria-current moved. After
completing step 1 the server returns:
<ol class="hc-stepper"> <li class="hc-stepper__step" data-state="complete"> <span class="hc-stepper__marker" aria-hidden="true">✓</span> <span class="hc-stepper__label">Account <span class="hc-sr-only">(completed)</span></span> </li> <li class="hc-stepper__step" aria-current="step"> <span class="hc-stepper__marker" aria-hidden="true">2</span> <span class="hc-stepper__label">Profile</span> </li> <!-- …remaining steps unchanged (upcoming) --></ol>No client mutation: the marker content (✓ / 2), data-state, and
aria-current all arrive as markup.
Accessibility
Section titled “Accessibility”- An ordered list is the right bone structure: “list, 3 items” +
aria-current="step"is the standard idiom. - Markers are
aria-hidden(decorative duplicates of the position); the label text + sr-only suffixes carry the meaning. - RTL works for free (logical properties throughout, including the connector).
Theming tokens
Section titled “Theming tokens”Component tokens (in component.tokens.json) — semantic references, so
themes, accents and dark mode apply automatically:
| Token path | Purpose |
|---|---|
stepper.marker-size | Marker diameter (data-size="sm" overrides it). |
stepper.marker-bg / marker-fg | Upcoming-step marker. |
stepper.current-bg / current-fg | Current-step marker (follows data-color). |
stepper.complete-bg / complete-fg | Completed-step marker tint. |
stepper.connector | Connector line between steps. |
stepper.label | Label color. |
stepper.gap | Gap between marker and label. |
CSS variables
Section titled “CSS variables”Show the generated CSS variables
--hc-stepper-marker-size | -marker-bg | -marker-fg--hc-stepper-current-bg | -current-fg--hc-stepper-complete-bg | -complete-fg--hc-stepper-connector | -label | -gapRelated
Section titled “Related”- Multi-step form recipe — the wizard this indicates.
- Breadcrumb — location in a hierarchy, not progress in a flow.
- Progress — continuous progress, not discrete steps.