Skip to content
microcharts
ReferenceDecisionDataDiff

DataDiff

React data diff chart — before/after series divergence for a release or experiment. Tiny accessible SVG microchart; RSC-safe static or /interactive.

DataDiff answers "what changed between these two versions?". Each key gets a diverging bar: removed leftward, added rightward, both always drawn on one symmetric shared scale. Net is a mark you can turn on, never a replacement for the two bars — a +500/−480 churn and a +20/−0 trickle must never look alike.

DataDiff
interactive · 5.3 kB · static · 2.74 kB

Install

Import & usereact/data-diff
import { DataDiff } from "@microcharts/react/data-diff";// diff — real values under “Sample data” below<DataDiff data={diff} title="Schema diff" />
Sample data
// a schema migration diff — rows added/removed per tableconst diff = [  { key: "users", added: 340, removed: 120 },  { key: "orders", added: 88, removed: 30 },  { key: "items", added: 40, removed: 20 },  { key: "tags", added: 24, removed: 8 },  { key: "notes", added: 12, removed: 6 },  { key: "flags", added: 8, removed: 3 },];
Needs package + stylesheetSet up with AI

Try it

When to use it

  • Good for — a table cell per dataset version, a KPI card for a sync or import job, any per-key added/removed audit where churn matters.
  • Avoid for — a plain ranking (MiniBar) or parts of a single whole (SegmentedBar).

Sizing

Variants

key tags + net + totals

Edge cases

empty diff
no changes anywhere

An empty data array renders an empty chart and reports "No data." A non-empty diff where every key is 0/0 still draws its hairline placeholder ticks and reports "No changes across 2 keys." — the keys are named even when nothing about them changed.

Four homes

Why this default

Both directions are always drawn, because net-only diffs hide churn: a table that added 500 rows and dropped 480 is not the same event as one that added 20 and dropped nothing, even though both net to roughly the same number. One symmetric scale spans every row so a big change never shrinks to fit a small one, and a key with no change still gets a hairline tick — the absence of a change is not the absence of the key. Cross-chart comparison goes through a shared domain.

Accessibility

The accessible name states the totals, the key count, and the single largest change — "+468 added, −170 removed across 3 keys; largest change: users (+220)." The interactive entry steps the rows and announces each key's added, removed, and net change.

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*{ key; added; removed }[]Per-key change counts — added and removed are non-negative magnitudes.
labelsbooleanIn-chart key tags for standalone use (host tables carry keys by default).
netbooleanA tick at added−removed per row — a summary mark, never the two bars.
order"data" | "net" | "magnitude"Default 'data' keeps input order (schema order is often meaningful).
label"totals" | "none"'totals' prints a +added / −removed footer.
maxItemsnumberRow cap (default 12); rows beyond it are dropped with a dev warning.
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