# Chronicle

A zoomable, multi-lane timeline for incidents, releases and audit trails — spans, instants, a playhead and an overview brush.

- Family: Signature, imported from `mizu-ui` or `mizu-ui/signature`
- Docs: https://mizu.user64bit.world/components/chronicle
- Source: https://github.com/0xuser64bit/mizu/blob/main/packages/mizu/src/signature/Chronicle.tsx

## Usage

```tsx
import { Chronicle } from "mizu-ui";

export function Example() {
  const at = (h: number, m: number) => Date.UTC(2026, 8, 27, h, m);
  return (
    <Chronicle
      label="Checkout incident"
      utc
      lanes={[
        { id: "deploys", label: "Deploys" },
        { id: "api", label: "API" },
        { id: "alerts", label: "Alerts" },
      ]}
      events={[
        {
          id: "deploy",
          lane: "deploys",
          start: at(14, 2),
          label: "Deploy v2.41",
          tone: "accent",
          detail: "Canary promoted to every region.",
        },
        {
          id: "latency",
          lane: "api",
          start: at(14, 6),
          end: at(14, 31),
          label: "p95 above 2s",
          tone: "danger",
        },
        {
          id: "page",
          lane: "alerts",
          start: at(14, 9),
          label: "On-call paged",
          tone: "warning",
        },
        {
          id: "rollback",
          lane: "deploys",
          start: at(14, 24),
          label: "Rollback",
          tone: "success",
        },
      ]}
    />
  );
}
```

## Copy it with the shadcn CLI

```sh
npx shadcn@latest init 0xuser64bit/mizu/preset # once, where there is no components.json
npx shadcn@latest add 0xuser64bit/mizu/chronicle
```

## Props

- `label`: `string`. Accessible name and visible heading.
- `events`: `ChronicleEvent[]`. id, lane, start, optional end (omit for an instant), label, tone and detail content.
- `lanes`: `ChronicleLane[]`. Lane order and names. Derived from the events when omitted.
- `range / defaultRange / onRangeChange`: `[number, number]`. Visible interval in ms. Fits every event until the viewer moves.
- `cursor / defaultCursor / onCursorChange`: `number`. Playhead time. Supply either to show it and drive other views.
- `selected / defaultSelected / onSelectedChange`: `string | null`. Selected event id; its detail opens beneath the lanes.
- `now`: `number | Date`. Marks the present.
- `utc`: `boolean` (default `false`). Align and label time in UTC.
- `minSpan`: `number` (default `1000`). Smallest visible interval in ms.
- `loading / empty`: `boolean / ReactNode`. Loading and empty states.

## Keyboard

- ← →: Pan the viewport (Shift for larger steps)
- + −: Zoom around the playhead or centre
- 0: Fit every event
- Home End: Jump to the first or last events
- Ctrl + scroll: Zoom at the pointer (pinch on touch)
- ← → ↑ ↓: On an event: move through a lane, change lanes
- Enter · Esc: Select an event · clear selection

## Accessibility

The viewport is a focusable region with keyboard panning and zoom. Events form a listbox grouped by lane; each option names its label, time and duration, and selection is announced. The playhead is a slider with readable time. The overview brush is a pointer shortcut — every action has a keyboard path.

## Motion

Events sweep in left to right on first view. Button and keyboard zooms glide in log space so scale changes feel even; drags pan directly and coast to rest. Reduced motion removes the sweep, glide and coasting.
