# EventTimeline (/docs/charts/event-timeline)

An API had a freeze window overnight, nine healthy hours, an incident at 11:00, and a release at 20:00. EventTimeline
puts all of it on one row: diamonds mark instants, rects mark durations. The type distinction is a shape, so it survives
12 px where color coding wouldn't. Duration is length on a linear time axis, never log or compressed time.

```tsx
import { EventTimeline } from "@microcharts/react/event-timeline";

<EventTimeline
  data={[
    { start: Date.UTC(2026, 5, 3, 1), end: Date.UTC(2026, 5, 3, 5), label: "Freeze", kind: "accent" },
    { start: Date.UTC(2026, 5, 3, 6), end: Date.UTC(2026, 5, 3, 15), label: "Healthy", kind: "positive" },
    { start: Date.UTC(2026, 5, 3, 11), label: "Incident", kind: "negative" },
    { start: Date.UTC(2026, 5, 3, 16), end: Date.UTC(2026, 5, 3, 18), kind: "negative" },
    { start: Date.UTC(2026, 5, 3, 20), label: "Release" },
  ]}
  domain={[Date.UTC(2026, 5, 3), Date.UTC(2026, 5, 4)]}
  title="API uptime"
/>
```

## Install

```tsx
import { EventTimeline } from "@microcharts/react/event-timeline";

<EventTimeline data={windows} domain={today} title="API uptime" />
```

Setup (package + stylesheet): [Quickstart](/docs/quickstart#set-up-with-an-ai-agent) or paste [`/agent-setup.md`](/agent-setup.md) into your agent.

## Try it

```tsx
import { EventTimeline } from "@microcharts/react/event-timeline/interactive";

<EventTimeline
  data={windows}
  domain={today}
/>
```

## When to use it

Use it for per-service uptime rows, and for on-call shifts and release windows in cards. Avoid it past roughly 12 items;
for aggregated durations use a MiniBar of the totals.

## Sizing

**uptime rows (shared window)**

```tsx
{services.map((svc) => (
  <EventTimeline key={svc.id} data={svc.windows} domain={today} title={svc.name} />
))}
```

**with the current moment**

```tsx
<EventTimeline data={windows} domain={today} now={Date.now()} />
```

## Variants

```tsx
// authored, never implicit — determinism
<EventTimeline data={windows.slice(1, 3)} domain={today} now={Date.UTC(2026, 5, 3, 21)} />
```

```tsx
<EventTimeline
  data={[windows[1], { start: Date.UTC(2026, 5, 3, 16), end: Date.UTC(2026, 5, 3, 18), label: "Deploy", kind: "accent" }]}
  domain={today}
  label="spans"
/>
```

## Edge cases

```tsx
// no item has an end — every mark renders as a diamond, no span fill
<EventTimeline
  data={[
    { start: Date.UTC(2026, 5, 3, 9), label: "Deploy" },
    { start: Date.UTC(2026, 5, 3, 14), label: "Alert", kind: "negative" },
    { start: Date.UTC(2026, 5, 3, 18), label: "Resolved", kind: "positive" },
  ]}
  domain={[Date.UTC(2026, 5, 3), Date.UTC(2026, 5, 4)]}
  title="Today's events"
/>
```

```tsx
// the span starts before the window and ends after it — both edges cut
// flat at the domain boundary, never rescaled to fit
<EventTimeline
  data={[
    { start: Date.UTC(2026, 5, 2, 20), end: Date.UTC(2026, 5, 3, 10), label: "Maintenance" },
  ]}
  domain={[Date.UTC(2026, 5, 3), Date.UTC(2026, 5, 3, 6)]}
  title="Clipped window"
/>
```

A span that crosses the domain boundary is cut flat at the edge rather than rescaled to fit, so you see the part inside
the window and nothing more. An item that falls entirely outside the domain is excluded, with a dev-only console
warning. Spans that overlap render translucent in data order; that translucency is a legibility device rather than an
encoding, and the exact intervals are in the announcements.

## Four homes

**In a sentence**

```tsx
<p>
  API status today{" "}
  <span className="mc-inline">
    <EventTimeline data={windows} domain={today} width={90} height={14} summary={false} />
  </span>
  {" "}
  — 3 spans covering 63% of the window.
</p>
```

**In a table cell**

```tsx
<td>
  <EventTimeline data={windows} domain={today} width={90} height={14} />
</td>
```

**In a KPI card**

```tsx
<div className="kpi">
  <span className="figure">63%</span>
  <span className="unit">3 spans, 1 incident</span>
  <EventTimeline data={windows} domain={today} width={200} height={30} />
</div>
```

**In a tab header**

```tsx
<button className="tab">
  API <EventTimeline data={windows} domain={today} width={54} height={14} />
</button>
```

## Accessibility

The accessible name is the coverage read: **"2 spans covering 46% of the window; 0 events."** Coverage merges intervals
first, so overlaps never double-count. The interactive entry cycles items chronologically: spans announce **"Freeze: Jun
3, 01:00 to Jun 3, 05:00 — 4h."**, instants **"Incident: Jun 3, 11:00."**

The interactive entry follows the shared [interaction contract](/docs/accessibility#one-interaction-contract):
arrow keys rove between units on both axes, `Home` and `End` jump to the ends, and a click, tap, `Enter` or
`Space` selects a unit — pinning its readout so it survives blur, until you select it again, press `Escape`, or
press outside the chart. On touch, a tap pins and a drag scrubs.

## Props

| Prop | Type | Description |
| --- | --- | --- |
| `data` (required) | `{ start; end?; label?; kind? }[]` | Spans (with end) and point events (without), ms epoch or Date. |
| `domain` | `[start, end]` | The window — fix it across rows for small multiples. |
| `now` | `number \| Date` | Current-moment tick; authored, never implicit. |
| `label` | `"none" \| "spans"` | Centered in-span labels with deterministic drop-out. |
| `dateFormat` | `Intl.DateTimeFormatOptions \| (d: Date) => string` | (interactive) Announced timestamp format for focused events (defaults to a locale date-time). |
| `animate` | `boolean` | (interactive) Opt-in entrance motion when the chart mounts client-side — add `import "@microcharts/react/motion"` once. Inert on the server, on hydrated server HTML, and under `prefers-reduced-motion`. |

Plus the shared grammar — `data`, `domain`, `color`, `title`, `summary`, `format` — and the layout props (`width`, `height`, `className`, `style`) that every chart accepts. Interactive entries also share `animate` and `live`, and — wherever a chart has more than one navigable unit — `onActive`, `onSelect`, `selectedIndex` and `defaultSelectedIndex`; and — wherever the chart shows a hover value — `readout`. See [the shared grammar](/docs/quickstart#the-shared-grammar).
