Timelines & steps
Things that move through stages: event timelines, trackers, pipelines, traces, rollouts, gates, paths and roadmaps.
Installation & usage
npx @youj/cli add app-event-timelineAlso installs async-button, badge, button, card, dropdown-menu, icon-more-horizontal, severity-timeline, share-bar, typography, use-announcer, use-controllable-state, use-now, use-visible, youj-core, youj-presets, youj-ui-core.
The CLI copies the block to blocks/app/event-timeline.tsx with every component it uses, so it’s yours to edit.
Every prop is optional and falls back to the demo, so it renders as you see it until you pass your own. Give it your data, rewrite or translate its strings through copy, and connect its actions:
'use client'
import { EventTimeline, type EventTimelineProps } from '@/blocks/app/event-timeline'
export function EventTimelineView({ event, phases, severities, statuses }: Pick<EventTimelineProps, 'event' | 'phases' | 'severities' | 'statuses'>) {
return (
<EventTimeline
event={event}
phases={phases}
severities={severities}
statuses={statuses}
copy={{ more: 'More actions' }}
onPhaseChange={(phase) => {
// your code
}}
onSeverityChange={(severity) => {
// your code
}}
onAdvance={async (phase) => {
// await your API here; the block shows progress until it settles
}}
/>
)
}Description
Something in progress as one card: a status pill, a level of urgency and a ticking open time, the time each phase took to reach, what it touches with a rate each, and a timeline of entries. Step it through your own phases (Acknowledge, Mitigate, Resolve; or Triage, Treat, Discharge), or raise its level.
Anything on a road of stages, replayed scan by scan on one rail: a parcel from ordered to delivered by default, a loan or a visa with your own stages. Retried stops, refusals and skipped stages are drawn too. Pick a stage for its details or another item from the tabs.
A run through ordered stages on one rail, with the selected stage's log tailing beneath it: a deploy from build to release, a bakery batch from mix to ship, an article from draft to publish. When every stage passes, Promote puts the result out; Roll back returns to what came before. The stages, the lines each prints and every word are yours.
A finished run read as time: steps grouped as Build and Deploy with when each started and how long it took, a strip across the top cutting the run into its groups, and the result line. Pass each step's previous time and it is compared: the earlier time is a longer ghost bar where the step got faster, an overshoot in the danger tone where it got slower, and a skipped step has only the word. It is StagePipelineRunTiming, a second part of the Stage pipeline block: it installs with it and is imported from blocks/app/stage-pipeline/run-timing.
One run as a graph of steps lit by state as it goes, with steps, elapsed time, size and cost counting up: an AI agent, a web request or a lab sample. Pick a step for its inputs and outputs, then approve the result.
One case as a card: its stage on a stepper, the verdict in a sentence with its confidence and the evidence behind it as one split bar, and the chain of events step by step, each step in its source's color with its offset from the first and a ribbon that shows the pace. The primary action finishes the current stage and moves the case on (a stage that stops things ends the step still running); Dismiss closes it. The demo is a security case (Triage, Investigate, Contain, Close, with Contain account ending the step still running), and Phishing case, Insurance claim and Fraud review show the same card with other stages and verdicts.
An item's rollout on a ruler cut into stages, snapped to gate by gate per environment, with exposure, a watched rate against its guardrail and a kill switch that rolls it back to zero. Feature flags in the demo; price variants by region or a firmware wave by ring of devices read the same, with the environments, stages and words yours. Every item is listed below with its own ruler.
The checks that gate a candidate before it goes through: a mobile release, a loan application, a site inspection. Its pass rate against the bar, the last candidates as lollipops and every group of checks as a row. Filter to the blocking groups, then go ahead once they clear.
A year of dated items on one ruler of fine ticks; the default is a product's roadmap, and a wedding or a renovation reads the same way. A pin per item, taller for the big ones, solid once done, hollow while upcoming and amber when it needs attention, with a bright tick for today and a count where items crowd one week. Hover anywhere along it (the nearest pin answers, and the ticks near the pointer stretch) or walk the pins with the arrow keys, and the callout says the date, status, title and one line about it; the one you pick stays shown. The foot says how many are done, how soon the next lands and how many need attention. Your own statuses name those figures. It has loading and error states that keep its size.
Intervals of work and rest: a ring with an arc per interval, the item at hand or a rest countdown, and a logger with count and amount steppers. Start, Pause and Skip drive the clock. The demo is an evening HIIT session; stories show focus and break cycles and a pour-over brew.
Code
Event Timeline, the Event timeline story: the files youj add writes.
blocks/app
Reference
Props30 props, 5 types
Props
| Prop | Type | |
|---|---|---|
theme | ThemeInputWraps the block in this theme. Default: the theme around it. | – |
embedded | booleanInside another app: a default true | true |
fill | booleanTake the whole width it's given instead of stopping at its natural width (736px at 100% scale). default false | false |
headingLevel | 1 | 2 | 3The title's heading level; the block's own sections sit one under it. Default 1, or 2 when | – |
locale | stringFormats durations and clock times. Default: | – |
copy | Partial<EventTimelineCopy>Any of the block's UI strings, to rewrite or translate. The event's own words are in | – |
event | EventTimelineEventThe event: its id, title, subject, lead and start. default the demo's INC-2817 on checkout-api | the demo's INC-2817 on checkout-api |
phases | EventTimelinePhase[]The stages it passes through, in order: the first is where it starts, the last closes it. default triggered, acknowledged, mitigated, resolved | triggered, acknowledged, mitigated, resolved |
severities | EventTimelineSeverity[]Levels of urgency, most urgent first (level 1), at most four. default SEV1 to SEV4 | SEV1 to SEV4 |
statuses | EventTimelineStatus[]How an item reads from its rate, worst first. default down, degraded, operational | down, degraded, operational |
scale | numberThe rate (0–1) at which an item's bar is full. default 0.4 | 0.4 |
format | { rate?: (rate: number) => string }Writes an item's rate (0–1). Default: a percentage with one decimal in the locale. | – |
phase | stringThe id of the phase it is in, when your app owns it; pair with | – |
defaultPhase | stringThe id of the phase it starts in, when the block owns it. Default: the first phase. | – |
onPhaseChange | (phase: string) => voidCalled with the new phase's id after the action that moves it has run. | – |
severity | SeverityLevel1234Its severity, 1–4, when your app owns it; pair with | – |
defaultSeverity | SeverityLevel1234Its severity at first, 1–4. default 2 | 2 |
onSeverityChange | (severity: SeverityLevel) => voidCalled with the new severity after Escalate, or when a phase eases it. | – |
entries | SeverityEvent[]What has happened so far, read when the block mounts (give it a new | – |
items | EventTimelineItem[]What it touches, each with its rate per phase. default the demo's three | the demo's three |
now | Date | numberThe time the block first renders at, in ms, which the server and the browser agree on; the clock ticks on from it once mounted. Default: the demo's fixed time with the demo events; with your own | – |
timeZone | stringClock times on the timeline in this zone, e.g. "UTC"; set it when you render on the server. Default: the browser's. | – |
live | booleanKeep the demo alive: new demo alerts arrive until someone acknowledges (never with your own default true | true |
demoMarker | booleanShows a dashed "Demo data" badge while the block runs on the demo's entries (no default true | true |
onAdvance | (phase: EventTimelinePhase) => Promise<unknown> | unknownMoves it into the next phase, which it receives; resolve when done, reject to show the message. Default: a short demo wait. | – |
onEscalate | (severity: SeverityLevel) => Promise<unknown> | unknown | – |
onCopyLink | () => voidThe menu's Copy link. Default: nothing. | – |
onOpenRunbook | () => voidThe menu's Open runbook. Default: nothing. | – |
onPostmortem | () => voidStart postmortem, once resolved. Default: nothing. | – |
classNames | { card?: string }Classes for its parts: | – |
EventTimelineEvent
| Prop | Type | |
|---|---|---|
idRequired | stringIts reference, set in mono: "INC-2817". | – |
titleRequired | stringWhat's wrong, as the heading: "Checkout errors". | – |
subjectRequired | stringWhat it is filed against, set in mono beside the id. | – |
leadRequired | stringWho's in charge, as people read it: "M. Oyelaran". | – |
leadHandle | stringThe lead's handle, the actor on the events the block adds. default `lead` | `lead` |
startedAt | numberWhen it began, in ms since the epoch. Default: its first entry. | – |
milestones | Record<string, string>Titles for the milestones the actions add, by phase id. Default: the phases' own. | – |
EventTimelineItem
| Prop | Type | |
|---|---|---|
idRequired | string | – |
nameRequired | stringSet in mono, as your tooling names it: "checkout-api". | – |
ratesRequired | Record<string, number>Its rate (0–1) in each phase, by phase id: it falls as the event is worked. | – |
EventTimelinePhase
| Prop | Type | |
|---|---|---|
idRequired | string | – |
labelRequired | stringThe status pill while it is here, and the milestone's word on the timeline: "Acknowledged". | – |
tone | Tone'accent''neutral''success''warning''danger'The pill's tone. Default accent. | – |
action | stringThe button that moves it into this phase: "Acknowledge". Not on the first phase. | – |
pending | stringThe button while that runs: "Acknowledging…". Default: the action. | – |
milestone | stringThe milestone event's title; | – |
announce | stringAnnounced to screen readers on arrival. Default: the phase's label. | – |
stat | { label: string; name: string }The time-to-reach figure in the row under the pill: its short label ("TTA") and spoken name. Not on the first phase. | – |
eases | EventTimelineSeverityLevel1234Moving into this phase eases the severity down to this level, if it is higher. | – |
EventTimelineSeverity
| Prop | Type | |
|---|---|---|
idRequired | string | – |
labelRequired | stringThe chip's text: "SEV1". | – |
name | stringThe spoken name. Default: the label. | – |
toneRequired | Tone'accent''neutral''success''warning''danger'Its tone, on the chip beside the pill and on the timeline's nodes. | – |
EventTimelineStatus
| Prop | Type | |
|---|---|---|
idRequired | string | – |
labelRequired | string | – |
toneRequired | 'success' | 'warning' | 'danger' | – |
from | numberThe rate (0–1) from which an item is in this status. default 0 | 0 |
Strings22 keys for copy
Strings
copy takes any of these keys; the rest keep their defaults. A key whose text holds a value (a count, a name) takes a function.
subtitlemorecopyLinkdemoDatarunbookopenclosedAfternotYetaffectednoItemsratetimelineentriesleadescalateescalatingescalatedescalatedDetailpostmortemfailedannounceEventlocaleBuilt from7 components
Built from
Accessibilitysteps, listboxes, meters, motion
Accessibility
Event timeline reads out its level of urgency (hidden text beside the badge), the timeline is a labelled list, and failed actions use role="alert". The open time is not announced as it ticks.
The step tracker lists its stages as an ordered list named for the item. Each stage is a button with a full spoken label, aria-pressed for the one you picked and aria-current="step" for where the parcel is; the arrow keys move along the road, and the stage details panel is linked with aria-controls. The item tabs and the Replay button are named, and the decorative dots are aria-hidden.
In Stage pipeline each stage is a labelled toggle with its name, state and duration, and the arrow keys, Home and End move between stages. The log is role="log" named by its title; it is a polite live region while it follows the newest line and goes silent once you scroll up or pause.
Step trace's steps are one tab stop, arrow keys follow the flow direction, and the detail's close button is labelled.
Case file shows its stage on a Stepper whose current step is aria-current="step" and whose every step says its state. The signals bar is a meter whose value text names every signal with its share, and the key under it repeats them as text. The chain of events is a named list, oldest first, each step with its clock time, how long after the first it came, its source and what it touched; the step still running says Ongoing. Contain, Close and Dismiss announce the new stage in a polite live region, and a failed action says why in its button.
Staged rollout puts a named meter on each ruler, with the stage spoken (for example "Internal at 1%"). The playhead steps with the keyboard, the environment switch is labelled, and each item in the list is a button with aria-pressed. The stories show other worlds, with their own names and words.
Check gate draws its history as an image with a text alternative that gives the candidate count, how many fell under the bar and the candidate's pass rate; the lollipops themselves are aria-hidden. The All / Blocking filter is a named control.
Roadmap timeline draws its year as a named listbox of items, one tab stop: the arrow keys walk the pins, Home and End go to the ends, and selection follows focus. Every pin is named with its title, day and status in words ("SSO and audit log, Oct 28, At risk"), a shared pin names all of its items, and the one-line description is the pin's description; the callout repeats it visually. Status is a word and a solid, hollow or amber dot, never color alone, and the foot's figures are a description list.
In both stories the progress path is a labelled group with one tab stop, and arrow keys move between steps, with a hidden hint. The points and daily goal meters are named, the week's flames are a labelled ordered list with each day's points written out, and finishing a step is announced in a status region.
Interval timer's ring is a labelled group, and the timer is role="timer" with live announcements off so it does not chatter every second; the ring announces each interval and ticks through the last three seconds. Add 15 seconds and Skip rest have explicit labels.
Under reduced motion numbers, rings and the trail are drawn in place.
Each card is a section named by its title. Under reduced motion cells and rows change in place.