Skip to content
microcharts
ReferenceCoreEventTimeline

EventTimeline

React event timeline chart — sparse events on a compact timeline you can scan inline. Tiny accessible SVG microchart; RSC-safe static or /interactive.

EventTimeline answers "what happened when, and for how long?" — uptime windows, on-call shifts, release spans and incident points 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.

EventTimeline
interactive · 5.53 kB · static · 2.88 kB

Install

Import & usereact/event-timeline
import { EventTimeline } from "@microcharts/react/event-timeline";// windows, today — real values under “Sample data” below<EventTimeline data={windows} domain={today} title="API uptime" />
Sample data
const windows = [  { 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" },];const today: [number, number] = [Date.UTC(2026, 5, 3), Date.UTC(2026, 5, 4)];
Needs package + stylesheetSet up with AI

Try it

When to use it

  • Good for — per-service uptime rows, on-call shifts and release windows in cards.
  • Avoid for — more than ~12 items, or aggregated durations (MiniBar of totals).

Sizing

Variants

now tick
span labels

Edge cases

instants only
clipped by the window

Four homes

Why this default

Duration is length on a linear time axis — never log or compressed time. Items that overlap the window edge are clipped flat (honest partial visibility); fully-outside items are excluded with a dev warning. Overlapping spans render translucent in data order — a legibility device, not an encoding; the exact intervals live in the announcements.

Accessibility

The accessible name is the coverage read — "2 spans covering 46% of the window; 0 events." — where 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: 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 or press Escape. On touch, a tap pins and a drag scrubs.

Props

PropTypeNotes
data*{ 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.
nownumber | DateCurrent-moment tick; authored, never implicit.
label"none" | "spans"Centered in-span labels with deterministic drop-out.
dateFormatIntl.DateTimeFormatOptions | (d: Date) => stringinteractiveAnnounced timestamp format for focused events (defaults to a locale date-time).
animatebooleaninteractiveOpt-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.

Related charts