A vertical list of the steps of a multi-step flow, each with its status and description.
Step 2 of 3, Pick up, in progress
A vertical list of the steps of a multi-step flow, each with its status and description.
Step 2 of 3, Pick up, in progress
ProgressStepsList shows every step of an ordered flow with its details — a courier delivery: go to the sender, pick up, go to the recipient, drop off. Each step is a row: a small squircle whose look follows the step's status, on a line that runs down to the next step, and beside it the step's description — DefaultItem, a Cell with a title and a subtitle, or a team's own layout. It is the full form of the flow; ProgressStepsCompact is the compact row that opens it.
Step 2 of 3, Pick up, in progress
Step 2 of 3, Pick up, in progress
Loading
The list has three states — Standard, Skeleton and Disabled. Each step shows its status through the Squircle's own states; a tappable DefaultItem presses and takes focus as a Cell.
Step 3 of 4, Go to recipient, in progress
Loading
Loading
.squircle--skeleton: --skeleton-on-white, content hidden, the shimmer --pattern-shimmer.
.skeleton bars: full width × var(--sp-100-s16), then var(--sp-100-s120) × var(--sp-100-s12); radius var(--sp-100-s8), var(--sp-100-s4) apart and above and below.
.progress-steps-list--skeleton, data-ds-state="skeleton"; the placeholder list is aria-hidden; the phrase reads "Loading" — no aria-busy: the phrase is the live region, and a busy one holds its own announcement back.When the steps land, the host swaps the rows in the same root and writes the position into the same phrase — announced once.
Step 2 of 3, Pick up, in progress
Step 2 of 3, Pick up, in progress
.squircle--disabled: --surface-on-white with --text-and-icon-disabled — in place of its status.The statuses are not drawn; each step's prefix still speaks them.
.is-disabled — title, subtitle and chevron in --text-and-icon-disabled.A tappable DefaultItem carries aria-disabled="true" — reachable, the press and the tap refused. A team's own content handles its Disabled itself.
.progress-steps-list--disabled and data-ds-state="disabled". Not staged in Figma — an owner ruling.
Step 2 of 3, Pick up, in progress
:focus-visible only.
A vertical stack of rows, one per step: a squircle on a line that runs down to the next step, and the step's description beside it.
Step 2 of 3, Pick up, in progress
cell-chevron and the whole cell is the target.
Paddings and gaps are fixed (SP/100%), the squircle stops at 130 %, the text scales in full.
Step 2 of 3, Pick up, in progress
Step 2 of 4, Pick up, in progress
Step 2 of 4, Pick up, in progress
person-courier, info-outline (current), courier-walk, courier — a 24 glyph, var(--sp-s24), in the squircle's content colour.
dir="rtl": StartSlot on the right, the text aligned right; the chevron and courier-walk (.progress-steps-list__icon--rtl) mirror, the numbers and other icons do not.
.squircle--text) or an icon (the bare .squircle--s). One content type per list.
Step 1 of 4, Go to sender, in progress
Use ProgressStepsList for the full breakdown of an ordered flow, each step described — a courier route, a multi-stop ride, a document check — and as the screen ProgressStepsCompact's MoreButton opens. Where only the position matters and space is tight, use ProgressStepsCompact. Not for a continuous value (a Progress Bar), not as a stepper that moves the flow, not for a list with no order (Cell rows).
Delivery route
Step 2 of 4, Pick up, in progress
Delivery route
Step 2 of 3, Pick up, in progress
58 Zhandosov Street, Residential Complex
Courier: Dilnaz Ahmetov
58 Zhandosov Street, Residential Complex
Courier: Dilnaz Ahmetov
56 Samal-2 Micro District, Building 4
Courier: Dilnaz Ahmetov
Step 2 of 3, Pick up, in progress
Step 2 of 3, Pick up, in progress
.progress-steps-list__step; an IconContainer adds .progress-steps-list__step--icon-container and takes its colour through its own color.
data-ds-preset="custom". A re-pointed colour is the team's contrast check; the spoken prefixes are unchanged.
An ordered list, one element per step, read as its position and status first. The squircles, numbers, icons and Dividers are not announced. Full spec: progress-steps-list-a11y.md.
Step 2 of 3, Pick up, in progress
mergeDescendants) with collectionItemInfo; the StartSlot is cleared. VoiceOver: children: .combine, the StartSlot hidden.Web: an <ol role="list"> of <li> — the explicit role because WebKit drops a list-style: none list's semantics; the prefix a .visually-hidden span inside the title; the StartSlot and chevron aria-hidden. No aria-current — the prefix already says "in progress".
Role.Button; VoiceOver .button, hint "Opens the step's details."The trap: the cell is 40 high; growing it to 48 in layout moves the Divider. The touch region expands instead — on the web a transparent ::before var(--sp-100-s4) beyond its top and bottom.
.visually-hidden paragraph with role="status" names the current step — "Step 2 of 8, Pick up, in progress". It stays in the DOM and only its text changes, so a change is announced once and the first render is not.TalkBack: a polite liveRegion on a summary node before the list — a swipe stop by design. VoiceOver: a queued announcement (.accessibilitySpeechQueueAnnouncement) — a plain one interrupts.Cancelled steps are not appended — each says "cancelled" in its own prefix. In browse mode the phrase is read once before the list, and the current step again in its prefix — a deliberate repeat.
mergeDescendants, VoiceOver children: .contain), so every control inside stays its own target; the prefix is the step's first element, so position and status are read first.
aria-busy — it would hold the live phrase back.
aria-disabled="true" keeps the native button in the tab order but does not stop its Enter / Space click — the handler returns early while it is set.
CanvasText outline, the Divider takes GrayText, placeholders keep a GrayText edge.