component
An ordered sequence of events — a run history, an audit trail, an approval queue. Each item is a marker on a connecting line, with a heading, an optional date and a body.
The root is a role="list", so assistive tech announces how many events there are before reading them.
An item takes a title and an optional date; its children are the body. Give an item no date at all and it is simply a labelled step.
main.---
import { Timeline, TimelineItem } from "../../index";
const RELEASED = new Date(2026, 0, 12);
const REVIEWED = new Date(2026, 1, 3);
---
<Timeline>
<TimelineItem title="Opened" date={RELEASED} locale="en-US">
Merge request !402 opened against <code>main</code>.
</TimelineItem>
<TimelineItem title="Reviewed" date={REVIEWED} locale="en-US">
Three findings raised; two resolved in follow-up commits.
</TimelineItem>
<TimelineItem title="Awaiting approval">
Blocked on a human reviewer.
</TimelineItem>
</Timeline>date takes a single Date or a [start, end] range. Formatting lives in core (formatTimelineDate) rather than in each template, so all four frameworks print the same string — worth knowing because the rules have edge cases worth being consistent about:
title, the formatted date is promoted to the heading instead of rendering an empty one above it.Invalid date rather than throwing mid-render.Pass locale to format for a specific BCP 47 locale; it defaults to the runtime’s.
---
import { Timeline, TimelineItem } from "../../index";
const START = new Date(2026, 0, 5);
const END = new Date(2026, 2, 9);
---
<Timeline>
<TimelineItem date={START} locale="en-US">
No title, so the date becomes the heading.
</TimelineItem>
<TimelineItem title="Closed range" date={[START, END]} locale="en-US">
Both ends are shown.
</TimelineItem>
<TimelineItem title="Still running" date={[START, new Date()]} locale="en-US">
A range ending today reads as "… – now".
</TimelineItem>
</Timeline>feedback tints an item’s marker and its connecting line, so a run history can carry its own status at a glance. neutral is special-cased to a surface-and-border marker rather than a solid fill, which keeps a routine step from competing with the ones that matter.
---
import { Timeline, TimelineItem } from "../../index";
---
<Timeline>
<TimelineItem title="Primary" feedback="primary"
>Default marker colour.</TimelineItem
>
<TimelineItem title="Neutral" feedback="neutral"
>A colourless step.</TimelineItem
>
<TimelineItem title="Success" feedback="success"
>The pipeline passed.</TimelineItem
>
<TimelineItem title="Warning" feedback="warning"
>Bundle size grew by 40kb.</TimelineItem
>
<TimelineItem title="Danger" feedback="danger"
>A hardcoded secret was found.</TimelineItem
>
</Timeline>Each item takes an icon for the marker — a snippet in Svelte, a node in React, an icon slot in Vue, and a component in Astro. Without one the marker is a plain dot.
The `<TimelineItem>` entries, in order.
Bound reference to the root element (`bind:this`).
Per-slot style and HTML-attribute overrides.
Plus all standard <div> HTML
attributes.
When the event happened — a single date, or a `[start, end]` range. A range ending today renders as "… – now".
How the item is laid out relative to the line.
"primary"Semantic palette for the marker and connecting line.
BCP 47 locale for date formatting. Defaults to the runtime's locale.
Per-slot style and HTML-attribute overrides.
Heading for the item. When omitted, the formatted date is promoted to the heading and no separate date line is shown.