Steps
A vertical trace of a task as it runs: statuses, durations, and stages that open while they work and close when they are done.
c2-steps
A vertical list of steps: the trace of a task as it runs, or a wizard's progress. Each row is a marker, a label,
an optional dimmed detail beside it and trailing text at the end — a duration, a count, a timestamp.
A step with sub-steps is a group, and a group is a disclosure: its own row is the summary and its sub-steps
are the detail. Every step is a row, and every row is visible — a group starts expanded and nothing ever
folds one away on its own. The chevron is there for the reader, collapsed in the markup starts a stage folded,
and the run only ever brings a folded stage back into view when it starts running or something in it fails.
Author it either way, and mix them freely:
- Declarative — slot
c2-stepchildren and nest them for sub-steps. - Data-driven — hand it a
stepsarray of{ id, label, detail, trailing, status, children }and it renders the tree itself. The array wins when both are present. During a run,updateStep(id, patch)changes one step without rebuilding the array.
Everything the markup fills with a slot, the data-driven mode fills with a renderer: renderMarker for the
marker slot, renderToggle for toggle, renderLabel / renderDetail / renderTrailing for the text, and
renderItem for that text all at once. Each is handed the node, its depth, its position, its dotted path and
the status actually in effect.
A parent step that does not author a status takes one from its children: the most urgent thing inside wins, so
a stage reports that it is running, or that something under it failed, without you setting it.
current is the shortcut a wizard wants: set it to the index of the active step and every top-level step that
has neither an explicit status nor sub-steps becomes success before it, current at it and pending after.
A step that arrives while the list is already on screen grows into place rather than appearing, and a marker
gives one beat as its status settles — which is what a trace being written in front of you should look like.
--c2-step--enter-duration: 0s turns the first off, and prefers-reduced-motion turns both off.
The connector rail between markers is drawn by CSS and off by default, because a trace does not want one — give
--c2-step__rail--width a width and a stepper gets its rail.
Numbering follows the tree: marker="number" draws a dotted path, so the first child of the third step reads
3.1 rather than a second 1.
Attributes
| Name | Type | Default | Description |
|---|---|---|---|
marker | StepsMarker | icon | How each marker is drawn: a status glyph, the step's number, or nothing. |
current | number | -1 | Index of the active step, for a wizard. -1 (the default) leaves every status alone; otherwise a top-level
step with neither an explicit status nor sub-steps becomes success before this index, current at it and
pending after it. |
steps | StepNode[] | undefined | undefined | The steps as data, instead of c2-step children. Takes precedence over the slot. |
aria-label | string | null | null | Accessible name for the list. |
Slots
| Name | Description |
|---|---|
(default) | The c2-step children. Ignored when steps is set. |
Events
| Name | Type | Description |
|---|---|---|
step-toggle | CustomEvent<StepToggleEventDetail> | Fired by a c2-step when a group opens or closes, and bubbling to here. event.target is the step; detail.path says where it sits. |
CSS custom properties
Grouped by semantic target and state from --c2-component__target__state--property. Click a group to collapse it; click a name to copy it.
| Name | Type | Default | Description |
|---|---|---|---|
--c2-steps--gap | pixel | 0px | Space between rows. A stepper usually wants some; a trace does not. |
--c2-steps--background | color | — | |
--c2-steps--border | border | — | |
--c2-steps--border-radius | border-radius | — | |
--c2-steps--padding-block | padding | 0px | |
--c2-steps--padding-inline | padding | 0px | |
--c2-steps--overflow-y | overflow | visible | auto with a max-height keeps a long run in its own scroller. |
--c2-steps--max-height | max-height | none | |
c2-step
One row of a Steps list: a marker, a label with optional dimmed detail, and trailing text at the end
of the row — a duration, a count, a timestamp.
A step with sub-steps is a group. Nest c2-step children and the row becomes the summary of a disclosure
and the children its detail, so a long run collapses to the shape of the task rather than to a wall of lines.
There is no second element to learn: the same tag is a leaf or a group depending on what is inside it.
Every step is a row, and every row is visible. A group starts expanded and nothing ever folds one away on
its own: the chevron is there for the reader, and collapsed in the markup starts a stage folded. The run only
ever brings a stage back into view — a folded one reopens when it starts running (running, current) or
when something in it goes wrong (error, warning).
A step is one row. Label, detail and trailing text sit on a single line and truncate with an ellipsis rather
than wrapping, so a hundred-step trace stays scannable, and a sub-step is indented far enough that its marker
lands under its parent's label. --c2-step__text--flex-direction: column still stacks the detail under the
label, which a wizard's descriptions want — that is two lines on purpose, and each of them is still one line.
The step never sets its own depth, position or marker mode: the parent c2-steps writes them on every pass, so
a step used on its own renders as a single root-level row.
Attributes
| Name | Type | Default | Description |
|---|---|---|---|
status | StepStatus | pending | State of the step. Drives the marker glyph and the accent colour, and reopens a folded group. |
label | string | — | Primary text, when the label slot is empty. |
detail | string | — | Dimmed secondary text beside the label, when the detail slot is empty. |
trailing | string | — | Text at the end of the row, when the trailing slot is empty. |
collapsed | boolean | false | Whether this group is folded away. A group is expanded by default — every step in the list is a row you can see — and only the reader, the markup or a reopening status ever changes that. |
Slots
| Name | Description |
|---|---|
(default) | Sub-steps. A step that has them is a group. |
label | Primary text. Falls back to the label attribute. |
detail | Secondary text beside the label. Falls back to the detail attribute. |
trailing | Content at the end of the row. Falls back to the trailing attribute. |
marker | Replaces the whole marker: a custom icon, an avatar, a number of your own. |
toggle | A disclosure affordance of your own — a chevron, a caret. Empty by default: a trace is a list of rows, and the row is already clickable. It is filled per step, so give a leaf an empty <span slot="toggle"></span> to keep its rows lined up with the groups above them. |
Events
| Name | Type | Description |
|---|---|---|
step-toggle | CustomEvent<StepToggleEventDetail> | A group was folded away or brought back. Bubbles. |
CSS parts
Shadow DOM styling hooks used with ::part(name). Prefer CSS custom properties when they cover the change.
| Name | Description |
|---|---|
frame | The box around the whole step, which is what grows when a new step arrives. |
row | The row itself: toggle, marker, text and trailing content. A group's row is its <summary>. |
toggle | Disclosure region containing the assigned toggle slot for a group. |
marker | Round marker region containing the marker slot or status fallback at the start of the row. |
rail | The connector between this marker and the next. |
label | Primary-text region containing the label slot or property fallback. |
detail | Secondary-text region containing the detail slot or property fallback. |
trailing | End-aligned text region containing the trailing slot or property fallback. |
children | The box holding the sub-steps. |
CSS custom properties
Grouped by semantic target and state from --c2-component__target__state--property. Click a group to collapse it; click a name to copy it.
| Name | Type | Default | Description |
|---|---|---|---|
--c2-step--transition-duration | time | 150ms | Colour transitions, and the beat a marker gives when its status settles. |
--c2-step--enter-duration | time | 260ms | How long a step arriving in a running trace takes to grow into place. 0s turns the animation off. |
--c2-step--enter-translate | translate | -4px | How far it slides while it does. |
--c2-step__row--gap | pixel | 10px | Space between the marker, the text and the trailing content. |
--c2-step__row--padding-block | padding | 7px | |
--c2-step__row--padding-inline | padding | 12px | |
--c2-step__row--indent | pixel | calc(var(--c2-step__marker--size, 16px) + var(--c2-step__row--gap, 10px)) | Extra inset per level of nesting. The default puts a sub-step's marker under its parent's label, which is what makes the nesting read without drawing anything. |
--c2-step__row--border-radius | border-radius | — | |
--c2-step__row--background | color | — | |
--c2-step__row--border-bottom | border | 1px solid #e4e4e7 | The hairline under each row. |
--c2-step__row--outline | border | 2px solid rgb(2, 101, 220) | Focus ring of a group's row, which is a button. |
--c2-step__row__hover--background | color | — | Set it to make the rows respond to the pointer. |
--c2-step__toggle--size | pixel | 14px | Width of the toggle slot's column, when it is filled. |
--c2-step__toggle--gap | pixel | 4px | Space between that column and the marker. |
--c2-step__toggle--color | color | #a1a1aa | |
--c2-step__guide--color | color | #e4e4e7 | A vertical rule at each ancestor's depth, for a file-tree look. Off by default. |
--c2-step__guide--width | pixel | 0px | Width of that rule. 1px turns the guides on. |
--c2-step__marker--size | pixel | 16px | |
--c2-step__marker--font-size | font-size | 10px | Size of the dotted path in marker="number". |
--c2-step__marker--padding-inline | padding | 3px | Breathing room either side of a dotted path, which is what turns the circle into a pill when the number is long. Only marker="number" uses it. |
--c2-step__marker--font-weight | font-weight | 600 | |
--c2-step__marker--border-radius | border-radius | 999px | |
--c2-step__marker--border | border | 1px solid #bcbcc6 | The ring, drawn for the states that have no glyph of their own (pending, current, running) and for every marker="number" step. A finished step is its glyph, so it has no ring. |
--c2-step__marker--background | color | transparent | |
--c2-step__marker--color | color | #71717a | |
--c2-step__rail--width | pixel | 0px | Width of the connector. 0px is the trace look; 2px gives a stepper its rail. |
--c2-step__rail--color | color | #e4e4e7 | |
--c2-step__rail--gap | pixel | 4px | Space between the marker and the rail. |
--c2-step__label--color | color | #18181b | |
--c2-step__label--font-size | font-size | 13px | |
--c2-step__label--font-weight | font-weight | 500 | |
--c2-step__label--font-family | font-family | ui-monospace, SFMono-Regular, Menlo, Consolas, monospace | |
--c2-step__detail--color | color | #71717a | |
--c2-step__detail--font-size | font-size | — | Falls back to the label size. |
--c2-step__detail--font-weight | font-weight | 400 | |
--c2-step__detail--gap | pixel | 8px | Space between the label and the detail when they share a line. |
--c2-step__detail--row-gap | pixel | 2px | Space between them when they are stacked. |
--c2-step__text--flex-direction | flex-direction-row | row | column puts the detail on its own line under the label, which a wizard's descriptions want. It is the only variable that switch needs: the gap and the alignment follow it. |
--c2-step__text--align-items | align-items | baseline | How the label and the detail line up across the row. Stacked, they are flush left whatever this says. |
--c2-step__trailing--color | color | #71717a | |
--c2-step__trailing--font-size | font-size | — | Falls back to the label size. |
--c2-step__trailing--font-weight | font-weight | 400 | |
--c2-step__success--color | color | #16a34a | Marker colour when the step succeeded. |
--c2-step__error--color | color | #dc2626 | |
--c2-step__warning--color | color | #d97706 | |
--c2-step__running--color | color | rgb(2, 101, 220) | |
--c2-step__current--color | color | rgb(2, 101, 220) | |
--c2-step__skipped--color | color | #71717a | Marker and label colour when the step was skipped. |