ChangePoint
React change-point chart — regime breaks marked on a series with mean hairlines. Tiny accessible SVG microchart; RSC-safe static or /interactive.
ChangePoint answers "when did the behavior change level?". It shades alternating regimes, draws a per-regime mean, and marks the break where one level became another — because a spike means nothing without the regime it broke. The detector is a documented heuristic, not statistics; for production anomaly pipelines, pass your own break indices and the chart becomes pure annotation.
Install
import { ChangePoint } from "@microcharts/react/change-point";// errors — real values under “Sample data” below<ChangePoint data={errors} label="delta" title="Error rate" />Sample data
// error rate that stepped up on the 14th, then held — a clean level shiftconst errors = [ ...Array(14).fill(0).map((_, i) => 30 + ((i * 7) % 5) - 2), ...Array(20).fill(0).map((_, i) => 48 + ((i * 5) % 5) - 2),];Try it
When to use it
- Good for — context for an anomaly, an error rate / latency / cost that stepped to a new level, or annotating a
known deploy or incident (pass explicit
breaks). - Avoid for — a gradual trend (Sparkline) or a plain time series with no regime question.
Sizing
Variants
Edge cases
With a locale, the summary and delta label format their numbers in that locale's own grouping and decimal marks.
Auto-detection (breaks="auto") only runs at 8 or more points — a six-point series with an obvious jump still renders
as one flat, unbroken regime unless you pass breaks explicitly; this is deliberate, since a two-segment fit on that
few points is mostly noise. A single point has no line to draw and no break to find; data={[]} renders the frame with
the "no data" summary and no marks.
Four homes
Why this default
Context for every anomaly — the shading names the regime a value belongs to, and the break marks where the level truly
changed, so a reader sees "errors stepped up here" rather than "errors are high". The detector is a labelled
heuristic: a two-segment mean-shift found by binary segmentation, accepted only when the split both cuts the variance
enough and clears an effect-size threshold, so a constant series shows no break. It is a mean-shift test, not a trend
test: a steady ramp is still fitted as two regimes (the ramp variant above reports a shift around point 10), so pass
breaks explicitly when you already know the series is trending rather than stepping. For anomaly pipelines that
already know their breakpoints, breaks={[…]} turns the detection off and the chart becomes a faithful annotation.
Accessibility
The accessible name states the shift, the break, the regime means, and what happened after — "Level shifted up 60% around point 14 (mean 30 → 48); stable since." — or, with no detected shift, "No clear level shift across N points." The interactive entry steps the points with ←/→ (value + regime) and cycles the breaks with Tab, each announcing its mean shift.
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
| Prop | Type | Notes |
|---|---|---|
| data* | number[] | A single series. |
| breaks | "auto" | number[] | Explicit indices override the heuristic entirely — the production path. |
| maxItems | number | Max detected breaks (1–3). More regimes stop being glanceable. |
| means | boolean | Per-regime mean hairlines (default true). |
| label | "delta" | "none" | Signed % across the most recent break, in a gutter. |
| animate | boolean | interactiveOpt-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
CyclePlot
React cycle plot chart — seasonal slots with within-slot drift on a shared spine. Tiny accessible SVG microchart; RSC-safe static or /interactive.
EnsembleGhosts
React ensemble ghosts chart — faint ensemble paths with an emphasised median-like member. Tiny accessible SVG microchart; RSC-safe static or /interactive.