Timeline

Shows when each step of a run started and how long it took, with the slow and failed ones marked.

Examples

A failed run

Run run_8f2a9112.6sFailed
Run run_8f2a91
StepStarted atTookStatus
plan0ms0.5sOK
search_orders500ms2.1sOK
attempt 1500ms0.8sWarning
attempt 21.3s1.3sOK
issue_refund2.6s9.8sOK
refund_charge11.7s0.7sFailed
send_reply12.4s0.2sWaiting on you

A run in progress

Run run_77c0e43.0sRunning
Run run_77c0e4
StepStarted atTookStatus
plan0ms0.4sOK
search_orders400ms1.5sOK
draft_reply1.9s1.1sRunning

Quiet bars with a footer

Run run_8f2a914.3s

Open: model-l

Run run_8f2a91
StepStarted atTookStatus
plan0ms0.5sOK
model-l520ms2.1sOK
search_orders2.6s1.7sOK
attempt 12.6s0.8sWarning
attempt 23.4s0.9sOK

A prompt release waiting on a decision

Release of prompt v143.5min
Release of prompt v14
StepStarted atTookStatus
prepare0ms0.8minOK
evals48.0s1.4minWarning
release 10%2.2min1.0minOK
release 100%3.2min0.4minWaiting on you

Status

  • OK2.6s
    OK
    StepStarted atTookStatus
    search_orders400ms1.7sOK

    okdefault

  • Running1.8sRunning
    Running
    StepStarted atTookStatus
    search_orders400ms1.4sRunning

    running

  • Warn2.1s
    Warn
    StepStarted atTookStatus
    search_orders400ms1.7sWarning

    warn

  • Fail2.1sFailed
    Fail
    StepStarted atTookStatus
    search_orders400ms1.7sFailed

    fail

  • Waiting2.6s
    Waiting
    StepStarted atTookStatus
    search_orders400ms2.2sYour review

    waiting

States

  • Loading
    Loading
    StepStarted atTookStatus

    loading

  • Empty

    No steps yet.

    Empty
    StepStarted atTookStatus

    empty

Usage

When to use it
Use
A person asks where the time in a run went: steps, tool calls and model calls laid out on one clock.
Use
A run failed and the person needs the step that broke, in its place among the others.
Use
A prompt release or an eval that ran, or is running, as stages in order.
Not for
Records to compare across columns. Use Table.
Not for
Planning work that has not happened yet.

Rules

7 rules
Never
Put a Timeline in a Panel or beside Panels; it is a working surface, white with one grey edge and a rule under its header. Because a surface that scrolls, streams or is read closely needs the white frame's edge to show where it ends, and a white frame in a grey Panel is a box in a box.
Must
Pass start and end in milliseconds and let the timeline pick one unit; never format durations yourself. Because mixed units put 950ms beside 1.2s, so the bigger-looking number is the shorter step.
Must
Set status on the span that owns it, never on its parents. Because a parent marked failed puts a second wash on the run, so two rows read as the root cause.
Must
Give a timeline that can pass 200 spans a maxHeight so its rows window. Because without it every span renders, and a long agent run stalls the page each second it ticks.
Never
Use a Timeline to plan work; it shows what happened. Because a bar here means time spent, so a planned bar reads as work already done.
Should
Write label as the run it shows, with its id: "Run run_8f2a91".
Should
Give a waiting span the wait in waitingLabel, one to three words.

Accessibility

5 checks
The frame is a section named by label; the rows are a list, or a listbox with onSpanClick.
Each row is named "{label}, started at 1.2s, took 0.8s, failed".
With onSpanClick the rows are one tab stop: Up and Down move, Home and End jump, Enter opens.
A screen-reader table carries step, start, duration and status; the bars and the axis are aria-hidden.
Status is always a word; the wash and the bar colour never carry it alone. A narrow frame hides the status column, and the header and each row's name still say it.

Edge cases

8 edge cases
Running span
The bar has no end and grows to now, easing along between ticks of the clock.
Waiting span
A paper bar with an ink edge from the start to now and the waiting label, in the status column or after the bar when the frame is narrow.
Span under 1% of the run
Keeps a 4px bar so it stays visible.
Deep nesting
16px per depth; the name truncates and meta shrinks first; under 448px the meta goes.
1,000 spans
With maxHeight about 20 rows stay in the DOM.
No spans
"No steps yet." top-left in the body.
Right to left
Time runs from the right; names and the status column mirror.
Forced colors
Bars draw CanvasText; status stays a word.

API

9 props
label
string default required
spans
TimelineSpan[] default required
now
number
activeId, onSpanClick
string, (span) => void
kind
Kind
maxHeight
number
bars
'kind' | 'quiet' default 'kind'
footer
ReactNode
loading
boolean default false

Tokens

17 tokens
--line-frame
oklch(var(--ink-c) / var(--line-frame-alpha))
--line-row
oklch(var(--ink-c) / 0.08)
--accent-mark
var(--ink)
--accent-line
var(--ink)
--accent-wash
var(--surface-selected)
--ink
oklch(var(--ink-c))
--surface-skeleton
color-mix(in oklch, oklch(var(--grey-c)), oklch(var(--ink-c)) var(--skeleton-step))
--type-label
400 14px/16px var(--font-sans)
--type-label-sm
400 12px/16px var(--font-sans)
--type-tag
var(--type-code-sm)
--text-2
oklch(var(--ink-c) / 0.80)
--text-3
oklch(var(--ink-c) / 0.66)
--status-column
128px
--timeline-name
200px
--timeline-name-min
120px
--radius-inner
4px
--radius-frame
10px

Install

For your coding agent

GitHub

Please star me pookie

141

A new design system every week

Leave your email before you copy the prompt.