Skip to content
microcharts
ReferenceFrontierPhaseTrace

PhaseTrace

React phase trace chart — cyclic phase as a compact trajectory on a shared ring. Tiny accessible SVG microchart; RSC-safe static or /interactive.

PhaseTrace answers "how do two coupled signals move together?". Plotting one against the other as a single trajectory turns lag into loops and regimes into clusters — structure that two separate sparklines hide. Path order carries time, and the current state is a directed endpoint with an arrowhead, so "now, and how it got here" reads at a glance.

PhaseTrace
interactive · 4.83 kB · static · 2.46 kB

Install

Import & usereact/phase-trace
import { PhaseTrace } from "@microcharts/react/phase-trace";// trajectory — real values under “Sample data” below<PhaseTrace data={trajectory} xLabel="CPU" yLabel="Latency" title="Phase portrait" />
Sample data
// a coupled CPU×latency trajectory with a lag loopconst trajectory = Array.from({ length: 40 }, (_, i) => {  const t = (i / 40) * Math.PI * 2;  return { x: 55 + Math.cos(t) * 22, y: 110 + Math.sin(t - 0.9) * 40 };});
Needs package + stylesheetSet up with AI

Try it

When to use it

  • Good for — coupled-signal phase portraits (CPU × latency, inflation × unemployment).
  • Avoid for — reading exact values (DualSparkline) or a single series (Sparkline).

Sizing

Variants

longer tail
locale

With a locale, the accessible summary's coordinates follow that locale's own grouping — "1.800" in German, not "1,800". In-chart marks carry no text, so only the announced numbers change.

Edge cases

single observation
steady (no motion)

A single observation draws only the accent endpoint dot — there's no history to trail and no motion for an arrowhead to point along. When every point in the tail window is coincident (or nearly so, within 0.5% of the combined axis span), the heading resolves to the fifth, explicit "steady" state rather than a jittery direction from noise.

Four homes

Why this default

A muted trail with an accent tail because "now, and how it got here" is the question — the eye lands on the recent motion first, then reads the history. Axis and scale choices are stated, never silently transformed: the axes are named in the summary, and the domains are always linear. The tail, endpoint, and arrowhead trio may be restyled but never all removed, because the recoverable time direction is what separates a phase trace from a scatter.

Accessibility

The accessible name states the current point and heading, with the y-axis named first — for the hero example above, "Latency vs CPU: now 76.729, 75.163; heading down-right." The interactive entry steps through the trajectory in time order with ←/→, announcing each point's index and its value on both named axes.

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, y }[]Two synchronized signals, time-ordered.
xLabel / yLabelstringAxis names — the summary reads them.
xDomain[number, number]Fix the x-axis range (default: the data's x-extent).
domain[number, number]Fix the y-axis range (default: the data's y-extent).
tailnumberFraction of points drawn in accent (recent motion).
gridbooleanQuadrant hairlines for regime reads.
startDotbooleanAnchor the path's origin for full-journey reads (default false).
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