v3.0.0
ProgressStepsCompact

A compact row of steps that shows how far a multi-step flow has progressed.

-- -- -- 3.0.2

Step 2 of 6, Pick up, in progress

Overview

ProgressStepsCompact shows where the user is in a flow made of ordered steps — a courier delivery: go to the sender, pick up, go to the recipient, drop off. Each step is a small squircle whose look follows its status, and a thin line joins neighbouring steps — a Divider by default, or a ProgressBar that shows the progress between them. It shows at most four steps; a longer flow ends in an arrow that opens the full list.

  • 1
    2 Steps
  • 2
    3 Steps
  • 3
    4 Steps
  • 4
    More

Step 1 of 2, Go to sender, in progress

Step 1 of 3, Go to sender, in progress

Step 1 of 4, Go to sender, in progress

Step 1 of 6, Go to sender, in progress

States

The row has three states — Standard, Skeleton and Disabled. Each step shows its status through the Squircle's own states; MoreButton presses and takes focus.

Step Status

Step 3 of 4, Go to recipient, in progress. Step 2, Pick up, cancelled

  • 1
    Completed Squircle Disabled — --surface-on-white with --text-and-icon-disabled.
  • 2
    Cancelled Squircle Standard with the content re-pointed — --squircle-content = --text-and-icon-error.
  • 3
    Current Squircle Inverse with the content re-pointed — --background-inverse-primary with --double-color-outline-inverse. One per row at most.
  • 4
    Upcoming Squircle Standard — --surface-on-white with --text-and-icon-primary.

Skeleton

Loading

Loading

Loading

  • 1
    Skeleton Steps Four Squircle S in their own Skeleton state — .squircle--skeleton: --skeleton-on-white fill, content hidden, the DS shimmer --pattern-shimmer.Static: four placeholders, whatever the row shows once loaded — 2, 3, 4 steps or 4 + MoreButton; it does not track the real number of StepItems. No MoreButton, no Counter. A matching shape is a custom-base job (Usage).
  • 2
    Connectors Dividers stay as they are — --border-default, as Figma stages the Skeleton row.ProgressBars take their Skeleton style — the whole bar a --skeleton-on-white placeholder with the shimmer.
  • 3
    Divider The Skeleton row with Dividers — the default connector.
  • 4
    ProgressBar The Skeleton row with ProgressBars — each bar a placeholder with the shimmer.
  • 5
    RTL The Skeleton row mirrored — the placeholders run from the right edge.
  • Loading Root: .progress-steps-compact--skeleton, data-ds-state="skeleton"; 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 placeholders for the steps and writes the position into the same phrase — announced once.Reduced motion: the shimmer resolves to none at the token; the fill alone shows the state.

Disabled

Step 2 of 6, Pick up, in progress

Step 2 of 6, Pick up, in progress

Step 2 of 6, Pick up, in progress, 60 percent

  • 1
    Standard The same row in Standard, for comparison.
  • 2
    Disabled · Divider The Disabled row with Dividers — the Dividers keep their colour.
  • 3
    Steps Every step's squircle takes its own Disabled state — .squircle--disabled: --surface-on-white with --text-and-icon-disabled — in place of its status.The statuses are not drawn; the phrase still speaks the position.
  • 4
    Connectors Dividers stay unchanged — --border-default.ProgressBars take their Disabled style — the track --surface-on-white, the fill --surface-contrast-overlay — whatever the style; the progress value stays.
  • 5
    MoreButton Its squircle is Disabled too; the "+N" Counter hides.aria-disabled="true" — it stays reachable, the press and the tap are refused; the label drops the count ("Show all steps").
  • Markup Root: .progress-steps-compact--disabled and data-ds-state="disabled". Not staged in Figma — an owner ruling.

MoreButton

Step 1 of 6, Go to sender, in progress

  • 1
    Standard The arrow at rest — a Squircle S Standard with the chevron, with or without the Counter.
  • Pressed Scales to 95 % — --component-push-button-press. A motion step; Figma stages no Pressed variant.
  • Focused Web, keyboard focus: an var(--sp-s2) outline in --text-and-icon-primary inside the squircle's edge — :focus-visible only. Tab to the arrow in the Animation demo to see it.

Anatomy

A full-width row of steps joined by connectors — Dividers by default, or ProgressBars — and, when the flow has more steps than fit, a trailing arrow with a counter.

Step 2 of 6, Pick up, in progress

  • 1
    Container A full-width row, items centred vertically; transparent — it sits on the host's surface.Required.
  • 2
    StepItem A Squircle S; its State follows the step status. The content is the step's number (Text) or an icon (Icon).Required, two to four.
  • 3
    Connector A line between two steps — var(--sp-s2) high, radius var(--sp-s16) — taking the free width. One kind per row.Divider (the default): --border-default.ProgressBar S: fills from the start edge to --progress-steps-compact-value (0–100), empty when unset; style Primary — the track --surface-contrast-overlay, the fill --background-inverse-primary. Drawn by the component — the DS ProgressBar is still planned.
  • 4
    MoreButton A Squircle S Standard with chevron-right — opens the full list of steps.Steps = More only.
  • 5
    Counter An Indicator M Number — "+N", the steps hidden behind the arrow; --background-inverse-primary with --text-and-icon-inverse-primary.On with Steps = More — at least one step is behind the arrow; off only in the custom base. Hidden in the row's Disabled state.

Layout

One size. The row fills its host — 360 in the Figma set — and the connectors take what the steps leave; at most four steps, the fifth position is MoreButton. Paddings and gaps stay fixed (SP 100 %); the squircles cap at 130 %.

Steps

Step 1 of 2, Go to sender, in progress

Step 1 of 3, Go to sender, in progress

Step 1 of 4, Go to sender, in progress

Step 1 of 6, Go to sender, in progress

  • 1
    2 Steps The Divider stops at 48; the pair does not span the row.
  • 2
    3 Steps The Dividers share the free width.
  • 3
    4 Steps The most the row draws without MoreButton.
  • 4
    More Four steps and the arrow.
  • Row var(--sp-100-s20) — left and right padding.var(--sp-100-s12) — top and bottom padding.var(--sp-100-s4) — the gap between a step and a connector.64 high at 100 %: the squircle plus the vertical padding.
  • Step And MoreButton Squircle S — a 40 box, radius 16; Figma binds SP/130% ratio, so they stop at 52.var(--sp-130-s40) and var(--sp-130-s16) — the Squircle S box and radius on the web (Squircle 3.4.4).
  • Connector Divider or ProgressBar, the same box: var(--sp-s2) high (Figma SP/150% ratio); flex: 1 1 0 — the free width, down to zero.At a 360 host: 92 with three steps, ≈ 45 with four, 22 with More.
  • Two Steps — Connector Max Length With two steps the connector has a maximum length: --progress-steps-compact-progress-max = var(--sp-100-s48) (unbound in Figma).The pair keeps its own width — 136 at 100 % — and does not stretch across the screen; the alignment places it (start by default).Set by .progress-steps-compact--steps-2, only with two steps.
  • Four Steps At Most Positions 1–4 are steps; a fifth position is only ever MoreButton.The row draws steps 1–4 of the flow and does not scroll, wrap or shift; the rest go behind the arrow. Only the custom base changes this — any number of steps, fill or scroll (Usage).Its floor with More: 272 at 100 %, 332 at 130 / 150 % — the host gives at least that.
  • Counter var(--sp-100-s4) outside MoreButton's top-end corner, on both axes.

Connector

Step 1 of 6, Go to sender, in progress

Step 1 of 6, Go to sender, in progress

Step 2 of 6, Pick up, in progress, 60 percent

Step 2 of 6, Pick up, in progress, 60 percent

  • 1
    Divider The default connector.
  • 2
    ProgressBar, Empty No progress shown — the track alone.
  • 3
    ProgressBar With Progress 100 % after step 1, 60 % on the way to step 3.
  • 4
    ProgressBar, RTL The bar fills from the right.
  • Two Kinds Divider — the default: a static line in --border-default, .progress-steps-compact__divider. It keeps its colour in every state.ProgressBar — the second option, for a flow that shows progress between steps: .progress-steps-compact__progress with its fill. One kind per row.
  • Progress Between Steps ProgressBar only. Each bar shows how far the flow has moved from the step before it to the step after it: --progress-steps-compact-value on the bar, 0–100.Unset or 0 — the empty bar: the track alone.
  • ProgressBar Style Primary The default: the track --surface-contrast-overlay, the fill --background-inverse-primary. Other styles on the custom base (Usage); Disabled and Skeleton take their own (States).
  • Fill From the start edge — the right in RTL; it moves on transform with --transforming-state-default, zeroed under reduced motion.

Step Content

Step 1 of 6, Go to sender, in progress

Step 1 of 6, Go to sender, in progress

Step 1 of 6, Go to sender, in progress

  • 1
    Text The step's number.
  • 2
    Icon A courier delivery flow: person-courier (current), info-outline, courier-walk, courier, then MoreButton "+2".
  • 3
    Icon In RTL courier-walk mirrors; the other icons do not.
  • Text Or Icon A step holds its number (.squircle--text) or an icon (the bare .squircle--s, the SVG in .squircle__slot). One content type per row.The icon is a 24 glyph, var(--sp-s24), from icons/outlined/; it takes the squircle's content colour, so the status colours it like a number.
  • Directional Icons An icon the Figma library marks RTL (courier-walk) carries .progress-steps-compact__icon--rtl and mirrors under :dir(rtl), like the chevron.

Width And Alignment

Step 1 of 3, Go to sender, in progress

Step 1 of 6, Go to sender, in progress

Step 1 of 6, Go to sender, in progress

Step 1 of 6, Go to sender, in progress

Step 1 of 2, Go to sender, in progress

Step 1 of 2, Go to sender, in progress

  • 1
    Default The host's full width.
  • 2
    Max Width 360 — Start Capped through --progress-steps-compact-max-width, at the host's start.
  • 3
    Max Width 360 — Centre The capped row in the centre of the host.
  • 4
    Max Width 360 — End The capped row at the host's end.
  • 5
    2 Steps — Centre The pair in the centre of the row.
  • 6
    2 Steps — End The pair at the end of the row.
  • Full Width By Default The row takes its host's full width (width: 100%); the connectors absorb the extra.
  • Min And Max Width --progress-steps-compact-min-width and --progress-steps-compact-max-width, set on the instance or an ancestor; unset = no bound.A min width wider than the host overflows it — the host keeps room for it.
  • Alignment Start (the bare root) · .progress-steps-compact--align-center · .progress-steps-compact--align-end.It places the row in its host when a max width leaves room, and the two-step pair inside the row. Start and end are logical — they swap in RTL.

RTL

Step 1 of 2, Go to sender, in progress

Step 1 of 6, Go to sender, in progress

  • 1
    2 Steps The row hugs the right edge.
  • 2
    More The arrow at the left, the chevron mirrored.
  • Mirrored Row Step 1 at the right edge, MoreButton at the left. The chevron mirrors; the Counter stays on the top-end corner — the top-left. Numbers and icons do not mirror. The web takes the direction from dir="rtl".

Animation

Step 1 of 8, Go to sender, in progress

  • 1
    Live Demo An eight-step flow: steps 1–4 stay put, the arrow keeps "+4"; past step 4 the current step is behind the arrow. "ProgressBar" swaps the Dividers for ProgressBars, filled behind each passed step.
  • MoreButton Press --component-push-button-press — scale 100 % → 95 %.--component-push-button-release — back to 100 %.The scale alone — no Squircle state defines a pressed fill.
  • Status Change A swap: the step takes its new Squircle State in one frame — the Squircle declares no transition.
  • Current Step Moves The four drawn steps stay steps 1–4 — no shift, no scroll; only their statuses swap. Past the fourth step all four are passed and the current step is behind the arrow; the phrase still names it.
  • Skeleton Each placeholder runs the Squircle Skeleton's own sweep, --pattern-shimmer. Skeleton → Standard is a swap in one frame; the row's height does not change.
  • Disabled No press scale and no tap — :active:not([aria-disabled="true"]). Standard ↔ Disabled swaps the squircle states, no transition.
  • ProgressBar Fill A new value moves the fill on transform (scaleX from the start edge) with --transforming-state-default — Transforming/State/Default, the Progress Bar moment. Switch the live demo to ProgressBar: it fills the bar behind each passed step.The Divider is static — no motion.
  • Counter Change The "+N" count is the Indicator's own; the row adds no motion.
  • Reduced Motion --component-push-button-press, --component-push-button-release, --transforming-state-default and --pattern-shimmer resolve to zero at the token, so the press and the fill snap and the shimmer stops; no override of its own.

Usage

Use ProgressStepsCompact where only the position in a flow matters — a screen header, a card, the top of a bottom sheet. To describe each step — names, addresses, people — use the full list, ProgressStepList. Not for a continuous value such as a download (a Progress Bar), not as a stepper the user taps through, not for a single step or a flow with no order.

  • 1
    Long Flow Steps = More: steps 1–4 — the same four throughout the flow — and the arrow to the full list. Icon steps for a courier delivery.
  • 2
    Short Flow Steps = 2 · 3 · 4 — every step shows, no arrow.
  • 3
    Cancelled Step A cancelled step keeps its place in the row, its content in --text-and-icon-error.

Go to sender 10:15

Skyline Shopping Center

Step 1 of 6, Go to sender, in progress

Drop off

50 Nauryzbay Batyr St, Esentai Business Center

Step 4 of 4, Drop off, in progress

Go to recipient

The pickup was cancelled

Step 3 of 4, Go to recipient, in progress. Step 2, Pick up, cancelled

Custom Base

Step 1 of 6, Go to sender, in progress

Step 2 of 6, Order details, in progress

Step 3 of 4, Go to recipient, in progress

Loading

Loading

Step 3 of 6, Go to recipient, in progress

Step 6 of 10, Drop off, in progress

Step 5 of 6, Go to recipient, in progress

Step 2 of 6, Pick up, in progress

  • 1
    Main Preset For comparison.
  • 2
    IconContainer Steps Paddings var(--sp-100-s8) / var(--sp-100-s16), ProgressBar connectors in style Accent.
  • 3
    Re-Pointed Colours Squircle steps; the Completed content re-pointed to --text-and-icon-success, the Divider to --border-success.
  • 4
    Main Preset Skeleton Static: four placeholders, whatever loads.
  • 5
    Custom Skeleton Example 2's own Skeleton — four IconContainer-shaped placeholders and the arrow's place.
  • 6
    Fill Six steps, no MoreButton; the Dividers share the free width.
  • 7
    Scroll Ten steps in a horizontal scroller, Dividers at var(--sp-100-s24), the current step scrolled into view.
  • 8
    MoreButton At The Start With chevron-left — the passed steps 1–2 behind it, steps 3–6 drawn.
  • 9
    MoreButton Replaced A Button S Secondary, "All steps".
  • CustomProgressStepsCompact The base presets are built on (Figma 38824:5842). The structure stays — steps, connectors, the phrase; a team re-points what the main preset fixes, including the step count and MoreButton.An instance on the custom base carries data-ds-preset="custom".
  • StepItem Swap The Squircle may become another DS component — IconContainer in example 2. It keeps .progress-steps-compact__step; an IconContainer step adds .progress-steps-compact__step--icon-container and takes its status colour through its own color.The status still needs a visible difference besides colour where it matters, and the phrase still speaks it.
  • Paddings And Connector --progress-steps-compact-padding-block and --progress-steps-compact-padding-inline — unset, var(--sp-100-s12) and var(--sp-100-s20).Connector kind — Divider or ProgressBar, as on the main preset. Divider colour — --progress-steps-compact-divider, unset --border-default (example 3).ProgressBar style — .progress-steps-compact--progress-{style}, style = inverse · always-light · brand · accent · error · warning (Primary is the bare root). Inverse and AlwaysLight sit on dark surfaces, Brand on dark only (the colour rule).
  • Status Colours --progress-steps-compact-{status}-fill and --progress-steps-compact-{status}-content, status = completed · current · upcoming · cancelled.Unset, each is the Squircle state's own value; set, a semantic token, with its contrast checked.
  • Skeleton Shape The main preset's Skeleton is static: four Squircle S placeholders, whatever the row shows once loaded — 2, 3, 4 steps or 4 + MoreButton.A team that knows its flow draws its own placeholders on the custom base — DS Skeleton shapes (example 5) or Squircle Skeleton — in the matching count and form.
  • Any Number Of Steps The four-step limit is the main preset's; on the custom base a team draws as many StepItems as the flow has and picks the layout.Fill (example 6) — the main layout: the connectors share the free width, down to zero. Nothing scrolls, so the steps fit the host — 40 per step plus the gaps.Scroll (example 7) — __steps sits in .progress-steps-compact__scroller, which scrolls sideways; each connector takes --progress-steps-compact-connector-length, unset var(--sp-100-s24). No scrollbar; the host scrolls the current step into view.The scroller is focusable — tabindex="0", role="group", aria-label="Steps, scrollable" — so a keyboard can scroll the strip; its focus ring is an var(--sp-s2) outline in --text-and-icon-primary. The phrase still speaks the position.
  • MoreButton Optional On the custom base MoreButton may go (examples 6, 7), move — before __steps, at the row's start (example 8, chevron-left) — or be replaced by another DS component (example 9, a Button S Secondary).Whatever opens the full list stays a native button outside __steps with data-ds-action="open-all-steps" and data-ds-target="more-button", a label that says what it opens, and its own touch-target contract — a Button S is 40 and relies on the separation around it, which the row's padding gives. The phrase stays the first child, so the position is read before the button.

Accessibility

One element for the row, one button for the arrow. The squircles, numbers, icons, connectors and the Counter are not announced on their own.

Step 2 of 6, Pick up, in progress

  • 1
    One Element For The Row "Step 2 of 6, Pick up, in progress" — the position counts the whole flow, not the four drawn steps; the step's name comes from the host and is dropped when there is none.No step in progress: "3 of 6 steps completed", "6 steps, not started", "All 6 steps completed", "All 6 steps cancelled". Every cancelled step follows the position: "… Step 2, Pick up, cancelled". The ProgressBar after the current step adds its value when it shows progress: "…, in progress, 60 percent"; empty bars and the bars behind add nothing.TalkBack: clearAndSetSemantics with the contentDescription and a polite liveRegion — whether the first appearance is spoken is verified on a device. VoiceOver: children: .ignore, .staticText; a change is a queued announcement (.accessibilitySpeechQueueAnnouncement) — a plain one interrupts.Web: a .visually-hidden paragraph with role="status" stays in the DOM and only its text changes, so a change is announced once and the first render is not; the drawn steps are aria-hidden; no aria-label on the generic root.
  • 2
    MoreButton A button after the row: "Show all steps, 2 more" — the Counter joins the label and is not announced on its own. TalkBack Role.Button; VoiceOver .button, hint "Opens the full list of steps."The trap: the drawn box is 40, and growing it to 48 with minimumInteractiveComponentSize or a 48 .frame changes the layout — the row grows to 72. The touch region expands around the box instead; on the web a transparent ::before inset 4 outside it.
  • Keyboard And Focus Only MoreButton takes focus; Enter and Space activate it. An var(--sp-s2) outline in --text-and-icon-primary inside the squircle's edge, :focus-visible only. Order: the row, then MoreButton, in LTR and RTL — the reading order.Custom base, Scroll layout: the steps stay hidden, so .progress-steps-compact__scroller is the keyboard stop — tabindex="0", role="group", aria-label="Steps, scrollable", the arrow keys scroll it (WCAG 2.1.1); the same var(--sp-s2) ring in --text-and-icon-primary, Highlight in forced colours. The order follows the DOM: the phrase, then the scroller and MoreButton as drawn.
  • Contrast Upcoming ≈ 15.7:1 Day / ≈ 13.2:1 Night; Current ≈ 12.9:1 / ≈ 17.8:1 (DoubleColor/Outline-Inverse on InversePrimary); the Counter ≈ 17.0:1 / ≈ 17.8:1.Cancelled --text-and-icon-error ≈ 3.5:1 and Completed --text-and-icon-disabled ≈ 1.9:1 Day — under WCAG 1.4.3 for sighted users; the phrase carries the status for screen readers. The Figma colours stay — the gap is accepted (owner, 2026-11-12).Forced colours: the Current step and MoreButton draw system-colour outlines; the Divider and the ProgressBar track take GrayText, the fill the text colour; a disabled MoreButton and the skeleton placeholders outline in GrayText; focus stays Highlight.
  • Skeleton One element reading "Loading"; the placeholders are hidden and nothing takes focus — no MoreButton.TalkBack: the same node and polite liveRegion as the Standard row — only its contentDescription changes when the steps land. VoiceOver: one element labelled "Loading"; the arrival is a queued announcement.Web: no aria-busy — the phrase is the live region, and a busy ancestor would hold its announcement back.
  • Disabled The row keeps its phrase — the drawn steps no longer show the position, the phrase does.MoreButton stays reachable and refuses activation: TalkBack "Show all steps, Button, Disabled"; VoiceOver "Show all steps, Dimmed, Button", no hint. The count drops with the hidden Counter.The trap: 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.
  • Edge States A cancelled step is named in the phrase — no Error state of the row. Text scaling: the number (Main Body) scales to 150 % inside a box that stops at 130 %. RTL mirrors the row, the chevron and RTL-marked step icons; the phrase and the order are unchanged. Reduced motion: the press and the shimmer zero at their tokens.