Annotation A marker saying why the line moved. Deploys, incidents and campaigns explain most of the shapes on a dashboard, and without them every reader reconstructs the cause from memory. npx shadcn@latest add toggle-group npm i recharts Tokens this needs: --card, --muted, --muted-foreground, --border, --status-critical, --status-warn, --chart-1 The status, chart, scale, state and direction names are an extension, not a rename. shadcn has --destructive and five --chart-* and nothing else in this territory. ──────────────────────────────────────────────────────────────────────── // AnnotatedChart.tsx ──────────────────────────────────────────────────────────────────────── import { CartesianGrid, Line, LineChart, ReferenceArea, ReferenceLine, Tooltip, XAxis, YAxis } from "recharts"; import { ToggleGroup, ToggleGroupItem } from "@/components/ui/toggle-group"; import { cn } from "@/lib/utils"; /** * An event on the data's own axis. `to` is what separates a span from a * moment: a deploy has none, a maintenance window does, and the chart draws a * region for the second rather than flattening it into a line that loses the * duration. */ export type Annotation = { id: string; /** Epoch ms. */ at: number; to?: number; /** What lets a panel choose the events it cares about. */ tag: string; /** What happened, not only that something did. */ label: string; /** The deploy, ticket or incident behind the marker. */ href?: string; }; export type Sample = { t: number; value: number }; const hhmm = (t: number) => { const d = new Date(t); return `${String(d.getUTCHours()).padStart(2, "0")}:${String(d.getUTCMinutes()).padStart(2, "0")}`; }; const TICK = { fontSize: 10, fill: "hsl(var(--muted-foreground))" }; const POINT = "hsl(var(--chart-1))"; const REGION = "hsl(var(--status-warn))"; export function AnnotatedChart({ data, annotations, tags, shown, onShownChange, width = 420, height = 170, }: { data: Sample[]; annotations: Annotation[]; /** Every tag the source can deliver, in chip order. */ tags: string[]; /** The tags this panel shows. Forty deploy markers a day is a picket fence. */ shown: string[]; onShownChange: (tags: string[]) => void; width?: number; height?: number; }) { const visible = annotations.filter((a) => shown.includes(a.tag)); return (
hhmm(Number(t))} formatter={(v) => [`${v} ms`, "p95"]} /> {visible.map((a) => a.to ? ( ) : ( ), )}
{tags.map((tag) => ( {tag} ))} {/* The marker is a door, not a caption: the ticket is one click away. */} {visible.some((a) => a.href) && ( )}
); } ──────────────────────────────────────────────────────────────────────── // demo.tsx ──────────────────────────────────────────────────────────────────────── import { useState } from "react"; import { AnnotatedChart, type Annotation, type Sample } from "./AnnotatedChart"; /** Checkout p95 through an afternoon. Latency doubles at 14:07 and the deploy says why. */ const T0 = Date.UTC(2026, 8, 15, 13, 20); const at = (min: number) => T0 + min * 60_000; const DATA: Sample[] = [ [4, 140], [17, 180], [30, 150], [43, 240], [47, 430], [57, 400], [70, 370], [83, 190], [96, 230], [109, 270], [117, 300], ].map(([m, value]) => ({ t: at(m), value })); const EVENTS: Annotation[] = [ { id: "d-4a91c", at: at(47), tag: "deploy", label: "deploy 4a91c", href: "/deploys/4a91c" }, { id: "chg-2210", at: at(83), to: at(104), tag: "config", label: "maintenance", href: "/changes/2210" }, ]; const TAGS = ["deploy", "incident", "config"]; export default function Demo() { const [shown, setShown] = useState(TAGS); return (
); }