Skip to content
RU
Scale
Density
Theme
Accent

Navigation

Wizard steps

A sequence of the stages of a process with a mark of where it is now. The state is carried by a word under the label — the colour of the bar is not enough.

The component
  1. Sourcedone
  2. Rulesdone
  3. Checknow
  4. Launchnext
Markup
<ol class="inst-stepper">
  <li class="inst-stepper-item" data-state="done">
    <span class="inst-stepper-name">Source</span><span class="inst-stepper-note">done</span></li>
  <li class="inst-stepper-item" data-state="done">
    <span class="inst-stepper-name">Rules</span><span class="inst-stepper-note">done</span></li>
  <li class="inst-stepper-item" data-state="current">
    <span class="inst-stepper-name">Check</span><span class="inst-stepper-note">now</span></li>
  <li class="inst-stepper-item" data-state="todo">
    <span class="inst-stepper-name">Launch</span><span class="inst-stepper-note">next</span></li>
</ol>

Contract

What Required Why
An <ol> with <li> yes The steps are ordered, and the order is the whole meaning of the component
A data-state on every step, todo included yes The absence of the attribute is indistinguishable from a typo in it
An inst-stepper-note with the word of the state yes The colour of the bar has no right to be the only carrier

Accessibility

The order An <ol> reports the number of a step and their total without labels of the form "3 of 5"
Colour is not the only carrier The state travels as a word (inst-stepper-note) and as a bar
Contrast The name is --text-secondary (4.5:1), the word of the state --text-muted; this is data rather than decoration, and --text-faint is not due to it
The bar --accent-mark holds 3:1 against the --track — it is a mark rather than text
Type size The word of the state is --text-xs; the size does not go below 11px
Print The steps are printed: the word of the state reads on paper, where a bar might merge into it

Anatomy

The label of the state

inst-stepper-note is neither decoration nor a subheading. It is the second carrier of the state: "done", "now", "next" read on a printout and to somebody who does not tell the shade of the bar apart. A line with a date or a counter in that slot reports no state and does not replace it.

The layout

The strip wraps by itself: an item has flex: 1 1 10rem, and on a narrow screen the steps stand in several rows with not a single media query. The bar of the state is a ::before the full width of the item, so it does not part from the label at any number of steps.

States

data-state is a phase of life, and the vocabulary is the component's own and closed:

Example
  1. Passeddone
  2. Currentnow
  3. Upcomingnext
Markup
<ol class="inst-stepper">
  <li class="inst-stepper-item" data-state="done">
    <span class="inst-stepper-name">Passed</span><span class="inst-stepper-note">done</span></li>
  <li class="inst-stepper-item" data-state="current">
    <span class="inst-stepper-name">Current</span><span class="inst-stepper-note">now</span></li>
  <li class="inst-stepper-item" data-state="todo">
    <span class="inst-stepper-name">Upcoming</span><span class="inst-stepper-note">next</span></li>
</ol>
Value Means What it draws
todo Not begun yet. The base The bar --track, the label --text-secondary
current Happening now The bar --accent-mark, the label --text-primary and --weight-medium
done Finished The bar --accent-mark, the label --text-secondary

The base value todo is written in the markup, though there are no rules for it: a data-state="todo" is read and its absence is not, and a typo would look like the base.

A passed step and the current one share one colour of bar deliberately: what tells them apart is the inst-stepper-note — "done" against "now" — and the weight of the label. There is no second accent tone in the library.

API

Classes
NameWhat it does
class
inst-stepperThe list of steps. Put on an <ol>
inst-stepper-itemA step. The carrier of data-state
inst-stepper-nameThe name of the step
inst-stepper-noteThe word of the state under the name
Attributes
NameValueWhat it does
attribute
data-state—todo current done. Closed, with todo as the base
Tokens
NameValueWhere from
token
--gap-inlinevar(--space-4)base +14: density · scale
--space-24pxone across every cell
--space-48pxone across every cell
--text-sm0.875rembase +4: scale
--text-xs0.78125rembase +4: scale
--weight-medium600one across every cell
--size-marker2pxbase +4: scale
--radius-full999pxone across every cell
--tracklight-dark(oklch(0 0 0 / 0.10), oklch(1 0 0 / 0.16))one across every cell
--accent-marklight-dark(var(--a-4), var(--a-3))one across every cell
--text-primarylight-dark(var(--n-12), var(--n-1))one across every cell
--text-secondarylight-dark(var(--n-9), var(--n-5))one across every cell
--text-mutedlight-dark(var(--n-8), var(--n-6))one across every cell

Why the kit works this way — the constitution · Open source under MIT, github.com/keshon/instrument