Overview
Ordered step-by-step execution rail for async operations. Shows pending, running, waiting approval, succeeded, failed, timed-out, cancelled, skipped, and retrying states with per-step durations, attempt counts, action counts, optional progress indicators, nested child-workflow lanes, links, and expandable inline detail panels for logs, payloads, and errors.
Use RunStepTimeline for CI jobs, workflow engine runs, import pipelines, deployment flows, and queue workers. Use Timeline for timestamp-first event logs. Use Steps for interactive wizard navigation.
Overview
RunStepTimeline takes a steps array and renders an ordered list. Each step shows:
- A status dot on the rail (color-coded by state, decorative and hidden from assistive technology)
- A status badge (text label so state is not communicated by color alone)
- Start time, end time, and duration when available
- An attempt count badge when the step has been retried
- An action count badge when actions are available
- An optional link rendered with
Link - A progress bar for
running,retrying, orwaiting_approvalsteps with a knownprogressvalue - Indented child-workflow lanes from recursive
children - Expandable Collapsible panels for logs, payloads, and errors via the
detailsarray
The component marks the currently active step with aria-current="step". running, retrying, and waiting_approval are current, non-terminal states.
Usage
With expandable details
With inline detail panels
With nested child-workflow lanes
Branch / coordination groups
A top-level entry can be a branch group instead of a step. A branch group fans out into N parallel sub-lanes, each a sequence of steps with an optional outcome (won / lost / settled). The winning lane is emphasized, losers are muted, and the group is collapsible (collapsed by default once the lane count reaches collapseThreshold, default 3). Branch groups are opt-in via the kind: 'branch' discriminator, so existing RunStep[] arrays keep working unchanged — widen your array type to RunStepTimelineEntry[] to mix them in.
Rewound and compensated steps
Set rewound: true on a step that was speculatively executed and then unwound. It renders struck-through and de-emphasized (and announces its rewound state as text) while staying inspectable. Set compensates: '<forward-step-id>' on a step that reverses an earlier forward step, as in a saga rollback; the compensating step keeps its own place in execution order and renders inset with a dashed reversal connector and a Compensates <label> badge that names the forward step it reverses. The compensates id must reference a sibling step (one under the same parent); an unresolved id renders the step in place without the badge.
Step states
RunStepStatus is intentionally domain-agnostic. Map your domain state onto one of these:
pending— not yet startedrunning— currently executing within its lanewaiting_approval— paused on required approval and expected to continuesucceeded— completed successfullyfailed— completed with a terminal errortimed-out— exceeded its allowed execution timecancelled— stopped before it could completeskipped— bypassed intentionallyretrying— a prior attempt ended unsuccessfully; a new attempt is in progress
Map engine-specific deadline states such as timed_out, timeout, or deadline_exceeded to timed-out. Keep other terminal errors mapped to failed so consumers can present deadline expiry distinctly without introducing product-specific status vocabulary.
Props
RunStepTimeline props
RunStep shape
RunStepDetail shape
RunStepLink shape
Accessibility
RunStepTimeline renders an ol (ordered list) because steps are numbered and sequential. The list takes an accessible name via label (used as aria-label when neither aria-label nor aria-labelledby is provided directly).
The active step (running, retrying, or waiting_approval) receives aria-current="step" on its li element, matching the same pattern used by the Steps component. This allows assistive technology to identify which step is current without requiring a live region announcement.
Status dots on the rail are decorative: the marker element is marked aria-hidden="true" and inert. The status badge rendered as text includes an accessible label such as "Status: Waiting approval", so the step state is communicated to assistive technology through text, not color alone (WCAG 1.4.1).
Progress bars include an aria-label derived from the step label (e.g. "Build Docker image progress"), satisfying the ARIA progressbar accessible name requirement.
Expandable detail panels use Collapsible which implements the disclosure button pattern with aria-expanded and aria-controls wiring.
When to use
- Displaying the live or completed state of a multi-step async operation: CI jobs, workflow runs, import pipelines, or deployments.
- Showing a sequence where one step is currently active and prior steps have streamed in over time.
- Visualizing speculative parallel work (race N lanes, keep the winner) or saga-style compensation of a forward step.
- Guiding users through an interactive wizard where they choose what to do next — use steps instead.
- Showing a flat timestamp-first event log without structured step state — use timeline instead.
Examples
Basic run step timeline
A multi-step async run with pending, running, and succeeded steps.
Branch group with a winning lane
A speculative race across three parallel deploy candidates. The winning lane is emphasized and the losers are muted, with the group outcome summarized as text.
Failed and timed-out steps
Keep deadline expiry distinct from other terminal errors by mapping the engine timeout state to timed-out.
Rewound speculative step
A step that was speculatively executed and then unwound after a conflict. It renders struck-through and de-emphasized but stays inspectable, and announces its rewound state as text.
Saga compensation
A saga where a later step compensates (reverses) an earlier forward step by id. The compensating step renders inset beneath its forward step with a dashed reversal connector.
Temporal child workflow with approval wait
A Temporal-style workflow lane that moves from model planning to tool execution, waits on approval, then shows a retrying subagent lane.
Props
| Name | Type | Default | Required | Bindable | Description |
|---|---|---|---|---|---|
steps | RunStepTimelineEntry[] | req | Ordered list of timeline entries to render. Each entry is either a
{@link RunStep} or a {@link RunStepBranchGroup}. Plain RunStep[] arrays
remain valid — branch groups are opt-in via the kind discriminator. | ||
label | string | undefined | Accessible label for the timeline list.
Used as aria-label when aria-labelledby is absent. | |||
selectedStepId | string | null | undefined | Rendered step path key to visually mark as selected.
Accepts null so consumers can clear linked selection without omitting
the prop. Use the value passed to onStepSelect, or a row's
data-cinder-path attribute, for nested or branch-lane steps. | |||
onStepSelect | ((pathKey: string) => void)undefined | Fired when the user activates a rendered step row. Receives that row's rendered path key. | |||
children | Snippet<[RunStep]> | undefined | Optional per-step body content rendered after the step metadata. |