Steps
A step indicator that guides users through a task, with four states (wait / process / finish / error), vertical layout and clickable navigation.
Basic usage
In progress
Finished state
All finished
Initial step
Initial waiting
Four states
Set the state explicitly per step via the status field: wait waiting (secondary color + number), process in progress (primary color + number), finish done (success color + ✓), error error (danger color + ✕).
wait / process / finish / error
Clickable switching
With clickable enabled, step items are clickable to jump (the whole item is clickable and keyboard-reachable via Enter/Space); clicking fires oas-change (detail is { index }) and switches the current step.
Click a step to switch the current step
Steps with icons
Set the icon field per step (an built-in icon set key) to render an icon at the indicator position; an explicit icon takes priority over the status default icon (number / ✓ / ✕). When the icon is not found in the registry it is not rendered and falls back to the status default.
Icon steps
Linear mode
With linear enabled (combined with clickable/navigation), only steps with index <= current are clickable: past steps can be revisited, the current step stays put, and future steps are blocked with silent clicks (no oas-change).
Linear mode (no skipping)
Horizontal label placement
label-placement="horizontal" places the title on the same row as the icon (icon left, title right) with the connector line aligned to the icon center; the default vertical keeps the icon above the title.
Horizontal labels
Disabled steps
Disable a step with the disabled field: under clickable/navigation it is not clickable (no button semantics, skipped by keyboard) and visually weakened (weak color tokens); an explicit status still displays normally.
Disabled step
Progress dot
With progress-dot, the step indicator becomes a dot (the current step is enlarged with a soft halo) and the connector is a thin line; combined with clickable, dots are clickable to jump (keyboard included).
Progress dot
Navigation mode
With navigation, steps become an arrow navigation bar: the current step is highlighted in primary color, previous steps use a light primary tint, waiting steps are gray, and descriptions are hidden. Step items are implicitly clickable (no clickable needed). A "Previous / Next" button row is rendered at the bottom (disabled at the first/last step); clicking a step or a button fires oas-change (detail is { index }) and switches the current step.
Navigation mode (Previous / Next)
Without description
Titles only
Vertical
Vertical direction
Container status
The container-level status attribute (wait / process / finish / error) overrides the derived status of the current step (current index), e.g. to mark a whole flow as errored. An explicit per-step status still takes the highest priority.
Container status overrides the current step
Action hint
The per-step extra field renders a weak small hint line below the description (textContent rendering, no HTML injection).
extra hint
Step id passthrough
The per-step id field is echoed back in the oas-change event (detail: { index, id? }); steps without an id keep detail: { index } (backward compatible).
oas-change echoes id
Step-change guard
The oas-before-change event (cancelable) fires before a step change via a clickable step, keyboard Enter/Space, or the navigation Previous/Next buttons, with detail: { index }; the host can preventDefault() to veto the change. Useful for "block navigation while there are unsaved changes".
oas-before-change guard
Loading
The per-step loading field shows a CSS spinner at the indicator position (tokens); an explicit icon / number / progress ring yield to loading.
Loading step
Optional steps
The per-step optional field renders a weak "Optional" label next to the title (i18n: "可选" in Chinese / "Optional" in English, follows the locale).
optional marker
Without connector lines
lineless hides all connector lines (compact look, keeping indicators and status colors).
lineless
Compact mode
simple renders a compact single-row layout (smaller indicators, hidden descriptions, tighter connector lines). It is mutually exclusive with progress-dot / navigation (simple wins).
simple compact mode
Connector style
The separator attribute controls the connector style: line (default solid) / dashed (dashed border) / arrow (trailing arrowhead).
separator styles
Progress ring
The per-step percent (0-100) takes effect only on process steps: the indicator becomes a progress ring (SVG circle stroke-dasharray, tokens), yielding the number; ignored on non-process steps.
percent progress ring
Responsive vertical
With responsive, the component automatically renders in the vertical layout when the container width is below 640px (ResizeObserver, cleaned up on disconnect); an explicit direction is overridden by responsive, and navigation stays forced horizontal.
responsive narrow-screen vertical
Drag the bottom-right corner below 640px to switch the steps to the vertical layout automatically.
Custom numbering
The per-step prefix field renders custom numbering text (e.g. "A", "01") at the indicator position instead of the default number; priority: explicit icon > prefix > default number; the ✓/✕ of finish / error are unaffected (textContent rendering, no HTML injection).
prefix custom numbering
Middle collapsing
max-count (minimum 2) limits the number of visible steps: when exceeded the middle collapses into ellipsis steps (⋯, not clickable, connector lines stay continuous); the first step, last step and current step are always visible, and the window slides with current; invalid values / below 2 are ignored (show all).
max-count collapsing (click steps to see the window slide)
Reversed
reverse visually reverses the order (horizontal row-reverse / vertical column-reverse): the displayed number = total - index (increasing along the visual flow); status derivation still follows the steps array order and oas-change keeps echoing the array index.
reverse (horizontal / vertical)
Content on the right
content-placement="right" (horizontal mode, default bottom) places the title / description / hint block to the right of the indicator; ignored in vertical (vertical is already icon-left / content-right); orthogonal to label-placement.
content-placement right
Arrow segments
arrow renders an arrow-segment bar (horizontal only): each step is clipped into an arrow segment (first segment flat-headed, neighbors interlocking), active filled with the primary color / finished light primary / waiting gray; connector lines are hidden (segments join themselves); mutually exclusive with simple (simple wins), ignored under navigation.
arrow segments (with error state)
Arrow segment customization
arrow segment geometry and colors are exposed as CSS variables: --oas-steps-arrow-gap controls the gap between segments (set to 0 for interlocking flush edges, with neighbors distinguished by per-segment colors), --oas-steps-arrow controls the convex tip depth (deeper = blunter tip / smaller angle), and --oas-steps-arrow-item-bg-N (N=1..8) overrides the background color per segment (applies by DOM position; falls back to the status color when unset; beyond 8 segments it falls back to the status color).
Custom gap and per-segment colors (gap 0 interlock)
Custom gap (greater than 0, spacing between blocks)
Arrow depth / angle comparison
Combinations
Combination semantics: simple takes priority over progress-dot / navigation (dot and navigation shapes yield to simple); under navigation, responsive does not switch to vertical (navigation stays forced horizontal).
Combination: simple + progress-dot
Combination: navigation + responsive (still horizontal when narrow)
Size tiers
size offers five type-density tiers (xs / small / medium / large / xl, sm/md/lg aliases accepted, default medium). Tiers only change the title / description / step-number type scale — the indicator and connector geometry stays constant. Invalid values fall back to medium with a one-time warning.
Five size tiers
API
oas-steps
Attributes
| Attribute | Description | Type | Default |
|---|---|---|---|
arrow | Arrow-segment shape (horizontal only): each step is clipped into an arrow segment (first segment flat-headed, neighbors interlocking), active filled with the primary color / finished light primary / waiting gray, connector lines hidden (boolean; enabled when present; mutually exclusive with simple, simple wins; ignored under navigation) | boolean | — |
clickable | Steps are clickable to jump (boolean; enabled when present) | boolean | — |
content-placement | Content block placement: bottom (default, title/description below the indicator) / right (whole block to the right of the indicator, horizontal mode); ignored in vertical; orthogonal to label-placement | string | — |
current | Current step index (0-based) | string | 0 |
direction | Direction (forced to horizontal in navigation mode; responsive switches to vertical on narrow screens) | string | horizontal |
label-placement | Label placement: vertical (default, icon above title) / horizontal (icon and title on the same row) | string | — |
linear | Linear mode: only steps with index <= current are clickable (boolean; enabled when present; future steps are blocked, clicks are silent) | boolean | — |
lineless | Hide all connector lines (boolean; enabled when present; compact look) | boolean | — |
max-count | Maximum number of visible steps (minimum 2): when exceeded the middle collapses into ellipsis steps (⋯, not clickable, connector lines stay continuous); the first/last/current steps are always visible and the window slides with current; invalid values / below 2 are ignored (show all) | string | — |
navigation | Navigation mode: arrow bar with a bottom Previous/Next button row (boolean; enabled when present; mutually exclusive with simple, simple wins) | boolean | — |
progress-dot | Progress-dot steps: dot indicators with a thin connector line (boolean; enabled when present; mutually exclusive with simple, simple wins) | boolean | — |
responsive | Responsive vertical: renders in the vertical layout when the container width is below 640px (boolean; enabled when present; ResizeObserver, cleaned up on disconnect; ignored under navigation) | boolean | — |
reverse | Visual reversal: horizontal row-reverse / vertical column-reverse; displayed number = total - index (increasing along the visual flow), status derivation still follows the steps array order (boolean; enabled when present) | boolean | — |
separator | Connector style: line (default) / dashed (dashed border) / arrow (trailing arrowhead); not applied under navigation / arrow | string | — |
simple | Compact mode: single-row small size (smaller indicators, hidden descriptions, tighter connector lines) (boolean; enabled when present; takes priority over progress-dot/navigation) | boolean | — |
size | Five type-density tiers (indicator/connector geometry constant; aliases accepted) | string | medium |
status | Container-level status overriding the current step (wait / process / finish / error); an explicit per-step status still takes the highest priority | StepStatus | — |
steps | [{ title, description?, status?, icon?, disabled?, extra?, id?, loading?, optional?, percent?, prefix? }] JSON string | StepItem[] | string | [] |
Events
| Event | Description |
|---|---|
oas-before-change | Fired before a step change (cancelable, detail: { index }); the host can preventDefault() to veto the change (step clicks / keyboard / navigation buttons all apply) |
oas-change | Fired when a clickable step or a navigation button is clicked (including keyboard triggers); detail: { index, id? } (0-based; id echoes the step id field, keeps { index } when unset) |
CSS Variables
| CSS Variable | Description | Default |
|---|---|---|
--oas-steps-arrow | Convex tip horizontal depth of arrow segments (deeper = blunter tip); tied to the clip-path polygon | 10px |
--oas-steps-arrow-gap | Gap between arrow segments; 0 makes them interlock flush | 0px |
--oas-steps-arrow-item-bg-{1..8} | Per-segment background override (applies by DOM position, not data index); beyond 8 segments falls back to the status color | — |
--oas-steps-item-bg | Segment background for the current status (color-mix per status) | var(--oas-color-bg-hover) |
State rules: an explicit status (wait / process / finish / error) takes priority; otherwise it is derived from current — index < current is finish (✓), === current is process, and the rest are wait.