Skip to content
microcharts
ReferenceExpressiveConstellation

Constellation

React constellation chart — related points as a tiny connected constellation. Tiny accessible SVG microchart; RSC-safe static or /interactive.

Constellation answers "when did the rare events happen, and how big were they?" Each event is a dot placed by time (x) and value (y), with an optional magnitude driving its area-true size. A hairline line connects the events in time order, so the sequence of a handful of incidents reads at a glance. It is built for rare events — a dozen or fewer; dense streams belong to Seismogram or EventTimeline.

Constellation
interactive · 5.68 kB · static · 3.09 kB

Install

Import & usereact/constellation
import { Constellation } from "@microcharts/react/constellation";<Constellation  data={[    { x: 0, y: 40, m: 2 },    { x: 2, y: 90, m: 7 },    { x: 5, y: 30, m: 3 },    { x: 8, y: 65, m: 5 },  ]}  title="Incidents"/>
Needs package + stylesheetSet up with AI

Try it

When to use it

  • Good for — sparse incidents or outages on a timeline, milestones carrying a magnitude, or any rare events where the sequence is the story.
  • Avoid for — dense event streams (Seismogram, EventTimeline), a continuous trend (Sparkline), or precise value comparison (dot area is a low-precision channel).

Sizing

Variants

label the biggest, or drop the chronology line

Edge cases

empty
single event
no values — jittered layout encodes nothing

Empty data draws no marks at all — just the sized box — with "No data." as the summary. A single event has no line to draw — just one dot, and the summary says "1 event at …" rather than forcing a range. When every point omits y, the vertical spread is deterministic jitter for legibility only — the summary and the interactive readout never mention it, and the connector's slope carries no meaning in that mode.

Four homes

Why this default

The chronology line is on by default because the sequence is usually the story of rare events — you want to see the order and rhythm, not just a scatter. Dot size is area-true (r ∝ √m), because area is how the eye reads magnitude; it is a deliberately low-precision channel, so the number lives in the summary and the hover readout, not in a size you are asked to measure.

When no event carries a value, the vertical position is deterministic jitter that encodes nothing — it only spreads the dots so they do not stack. In that case the connector's slope is meaningless (it still runs in time order), and the summary never mentions vertical position. Time is sacred: the x position is never jittered, so simultaneous events sit at the same x.

Accessibility

The accessible name states the count, the span, and the largest event — "4 events between 0 and 8; largest at 8." The interactive entry lets you arrow through the events chronologically, each announced with its time, value, and magnitude through a polite live region; a hover readout shows the same. Magnitude is redundant with the dot size, never carried by it alone.

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*{ x: number; y?: number; m?: number }[]Events: x = time, y = value, m = magnitude (area-true size).
connectbooleanThe faint chronology line (default true).
label"max" | "none"Numeral at the largest event.
xFormat(x: number) => stringFormats time for the summary (e.g. a month name).
xDomain[number, number]Time (x) extent (default: data extent).
rBasenumberBase dot radius in viewBox units (default 1.6).
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