MicroScatter
React micro scatter chart — 2-D scatter with honest Pearson r in the summary. Tiny accessible SVG microchart; RSC-safe static or /interactive.
MicroScatter answers "are these two variables related?" — the relationship story no other micro chart tells. Dots render at 75% opacity so overplot reads as density instead of lying by occlusion, and duplicates are never jittered: position is the encoding.
Install
import { MicroScatter } from "@microcharts/react/micro-scatter";// pairs — real values under “Sample data” below<MicroScatter data={pairs} title="Latency vs error rate" />Sample data
const pairs = [ { x: 0, y: 0 }, { x: 1, y: 15 }, { x: 2, y: 30 }, { x: 3, y: 15 }, { x: 4, y: 30 }, { x: 5, y: 15 }, { x: 6, y: 30 }, { x: 7, y: 45 }, { x: 8, y: 30 }, { x: 9, y: 45 }, { x: 10, y: 30 }, { x: 11, y: 45 }, { x: 12, y: 60 }, { x: 13, y: 45 }, { x: 14, y: 60 }, { x: 15, y: 45 }, { x: 16, y: 60 }, { x: 17, y: 75 }, { x: 18, y: 60 }, { x: 19, y: 75 }, { x: 20, y: 60 }, { x: 21, y: 75 }, { x: 22, y: 90 }, { x: 23, y: 75 },];Try it
When to use it
- Good for — correlation in a sentence, two-metric relationships in KPI cards.
- Avoid for — more than 60 points (bin instead) or ordered time series (Sparkline).
Sizing
Variants
Edge cases
Empty data draws just the frame with "No data." as the summary. Under 3 points (or a zero-variance cloud) states the count and stops — no correlation claim without enough evidence to back it. Coincident points are never jittered apart: they overlap exactly, and at 75% dot opacity the overlap itself reads as extra density rather than hiding a point.
Four homes
Why this default
Axes are unlabeled at this scale, so title must name both variables, the way the hero demo above does. The summary's
relationship words are a documented heuristic on |r| (≥ 0.7 strong, ≥ 0.4 moderate, ≥ 0.2 weak), and whenever a
relationship word appears, r appears beside it: claim and evidence travel together. Fewer than 3 points, or a
zero-variance cloud, makes no claim at all.
Accessibility
The accessible name is the count plus the evidence-backed relationship — "24 points. Strong positive relationship (r 0.93)." — or just "2 points." when no claim is honest. The interactive entry steps points ordered by x and announces each formatted pair.
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* | { x; y }[] | Unordered pairs. |
| trend | boolean | Least-squares line — linear only, never smoothed. |
| focal | number | Accent one point — "this one, among all of them". |
| xDomain | [number, number] | X scale (domain keeps its grammar meaning: y). |
| domain | [number, number] | Y scale — the shared grammar name, paired with xDomain. |
| r | number | Dot radius, clamped [1, 3]. |
| 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
Slope
React slope chart — who rose and who fell between two moments, crossings readable at a glance. Tiny accessible SVG microchart; RSC-safe static or /interactive.
SegmentedBar
React segmented bar chart — part-to-whole as adjacent segments in one bar. Tiny accessible SVG microchart; RSC-safe static or /interactive.