use UI

Timeline

Also called activity feed, history, changelog, audit trail

A sequence of events shown in chronological order, each with its time and description.

Example

Release history — newest first

  1. Deployed

    v2.4.0 released to production by the release workflow.

  2. Approved

    Two reviewers signed off; one comment left unresolved.

  3. Opened

    Pull request #482 — “Replace the colour scale generator”.

  4. Branched

    Created from main at commit 2ba527d.

What the markup carries

<ol>  — the order is the content, so not <ul>
  <li> <time datetime="2026-08-08T09:14:00Z">Today, 09:14</time>
  the rail and the dots are ::before, never in the tree

“3 days ago” is for reading; the datetime attribute and the tooltip carry the absolute value, so a page cached for a week still says exactly when this happened. Each event also states its status in words — the green dot is not carrying that on its own.

When to use it

  • Events have a real order and the order is what the reader is here for — order history, deployments, an audit trail.
  • The gap between events matters: “three weeks later” is part of the story.
  • Each entry is short. A timeline is a spine, not a container for articles.

When not to

  • The items are a hierarchy. Nesting under a rail implies containment; that is a tree.
  • The list is long and the reader wants the newest only. A timeline of four hundred entries is a table wearing decoration.
  • There is no time dimension. A vertical line does not make an unordered list into a narrative.

Trade-offs

  • Order and rhythm are visible at once — bursts and gaps read straight off the rail.
  • Mostly semantic HTML, so it degrades to a perfectly usable list with no CSS at all.
  • Extends naturally: a new event is one more list item.
  • Costs a lot of vertical space per event, so it scales badly past a screenful.
  • The decorative rail is often built with elements that end up in the accessibility tree as noise.
  • Relative times (“2 days ago”) go stale in cached HTML and mislead anyone reading later.

Accessibility

What this pattern needs in order to work for everyone.

Keyboard
  • Nothing to operate unless entries link somewhere; then each link is a normal tab stop with a name that says where it goes.
  • Do not add `tabindex` to entries so they can be “navigated”. A list is read, not driven.
Roles and state
  • Use `<ol>` — the order is the content, and an unordered list throws that away. Newest-first is fine; say so in the heading.
  • Wrap each timestamp in `<time datetime="…">` with a machine-readable value, so “2 days ago” still resolves to a real date.
  • The rail, the dots and the connecting lines are decoration: `aria-hidden`, or draw them in CSS so they are never in the tree at all.
  • Icons that carry status need a text equivalent — a green tick beside “Deployed” is fine, a green tick alone is not.
Focus
If entries load as you scroll, do not move focus. Append below and let the reader arrive at their own pace.

In the wild

  • GitHub pull request timeline Commits, reviews and comments in one ordered stream, each with a real timestamp on hover.
  • Parcel tracking The clearest use of the pattern: a short list of events where the order is the entire message.