Step List
Step List
Use the step list to narrate work that happened in order: the steps a model took, the checks a job ran, the stages of a request.
The rail is all this component draws: the list, the row, the marker on each row, and the line connecting them.
What a step says is ordinary content, so compose the body from the type, tag, and spacing utilities you would use anywhere else.
That way a step can say anything without the step list growing a class for it.
The list is plain markup, so it works without JavaScript.
The PvStepList Vue component renders exactly these classes from an array of steps, and PvReasoning renders it from its steps prop.
Structure
| Class | Element | Description |
|---|---|---|
pv-step-list |
ol |
The list. Give it role="list", since it carries no markers of its own. |
pv-step |
li |
One step. Draws the rail to the step below it. |
pv-step-marker |
span |
The circle on the rail. Holds a pv-step-dot or a pv-icon-12 sprite icon. |
pv-step-dot |
span |
The dot inside a marker, in the marker's own colour. |
pv-step-body |
div |
Everything to the right of the rail. Add pv-flow-8 to space its lines. |
Status
Set data-status on the pv-step to colour its marker: complete fills it, active tints it, and pending (the default) leaves it neutral.
A step worth calling out can put a sprite icon in its marker instead of the dot; the marker colours the icon for you.
A row that leaves the marker out is something said between steps rather than a step of its own.
It indents to line up with the labels above it, and the rail runs unbroken through it.
Status also decides how much a step says.
A step that is done is a line the reader scrolls past, so it recedes to a quaternary label and nothing else.
The step still running is the one being read, so it is the only one at full weight and the only one that explains itself.
Composing a step body
These are the utilities the reasoning UI uses. Nothing here is specific to the step list, so swap any of it for what a step actually needs.
| Part | Classes |
|---|---|
| Label of the running step | pv-text-body-md pv-text-medium pv-text-default, plus pv-shimmer on the text while it runs |
| Label of a finished step | pv-text-body-md pv-text-quaternary |
| Artifact named by the label | pv-tag-highlight |
| Secondary line | pv-text-body-md pv-text-tertiary |
| Tags | pv-flex on the list, pv-tag-secondary with data-style="rounded" on each |
| Outcome | pv-text-body-md pv-text-medium pv-text-brand |
pv-shimmer paints across the whole of its box, so put it on the label text rather than on the row, or it sweeps the empty width beside the words.
A pv-flex label row does that for you: it shrink-wraps its children.
Example
A finished step, a running step, and a row with no marker.
-
Understanding the request
-
Checking the contracted rate
12 hospitals within 50 miles publish a rate for this code.
-
That gap is large enough to be worth explaining.
HTML
<ol class="pv-step-list" role="list">
<li class="pv-step" data-status="complete">
<span class="pv-step-marker" aria-hidden="true"><span class="pv-step-dot"></span></span>
<div class="pv-step-body pv-flow-8">
<p class="pv-text-body-md pv-text-quaternary">Understanding the request</p>
</div>
</li>
<li class="pv-step" data-status="active">
<span class="pv-step-marker" aria-hidden="true"><span class="pv-step-dot"></span></span>
<div class="pv-step-body pv-flow-8">
<p class="pv-flex pv-text-body-md pv-text-medium pv-text-default" style="--flex-wrap: wrap">
<span class="pv-shimmer">Checking the contracted rate</span>
</p>
<p class="pv-text-body-md pv-text-tertiary">12 hospitals within 50 miles publish a rate for this code.</p>
</div>
</li>
<li class="pv-step">
<div class="pv-step-body">
<p class="pv-text-body-md pv-text-tertiary"><em>That gap is large enough to be worth explaining.</em></p>
</div>
</li>
</ol>
Custom properties
Every value the rail draws is a custom property, so a consumer can retheme it without overriding rules.
The most commonly changed ones are below; the full set is in _step-list.scss.
| Custom Property | Default Value | Description |
|---|---|---|
--step-list-gap |
0.75rem | Space between the marker and the body |
--step-list-item-min-height |
2rem | Height of a row whose body is a single label, so the rail has room to read as a rail |
--step-list-marker-size |
9px | Diameter of the marker, and the width the rail centres in. A list whose markers hold icons widens this to --step-list-marker-icon-size on its own. |
--step-list-marker-dot-size |
9px | Diameter of the dot. Keep the difference from the marker even, or the dot lands on a half pixel. |
--step-list-rail-color |
#DCDFE4 | The rail |
--step-list-marker-dot-color |
#6E7784 | The dot, which at the default size is the whole marker. --step-list-marker-active-dot-color and --step-list-marker-complete-dot-color take over on a step with a status. |
--step-list-marker-complete-background-color |
#176F6F | Marker fill for data-status="complete", visible behind an icon |
--step-list-marker-active-background-color |
#E4F8F6 | Marker fill for data-status="active", visible behind an icon |
--step-list-shimmer-rgb |
247, 248, 248 | The RGB triplet pv-shimmer sweeps across a running label |