Skip to content
microcharts
ReferenceFrontierPhaseTrace

PhaseTrace

PhaseTrace plots two coupled signals against each other as one trajectory, with an arrowhead at the current state.

encodes
x×y trajectory; path order = time
precision
medium
nodes
≤ 5

CPU climbs and latency follows a beat later. PhaseTrace plots the two signals against each other as a single trajectory, so the lag becomes a loop and a regime becomes a cluster — structure two separate sparklines hide. Path order carries time, and the current state is a directed endpoint with an arrowhead, so you read where the pair is now and how it got there. The trail is muted and the recent tail accented, so the eye lands on the recent motion first.

PhaseTrace
interactive · 4.92 kB · static · 2.56 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

Use it for coupled-signal phase portraits: CPU × latency, inflation × unemployment. For reading exact values use DualSparkline; for a single series use Sparkline.

Sizing

Variants

longer tail

tail sets how much of the path is accented, and startDot marks the first observation. You can restyle the tail, endpoint, and arrowhead, but not remove all three: together they are what makes the time direction recoverable.

locale

With a locale, the accessible summary's coordinates follow that locale's own grouping: "1.800" in German rather than "1,800". In-chart marks carry no text, so only the announced numbers change. The axes are named in the summary and both domains are always linear, never silently transformed.

Edge cases

single observation
steady (no motion)

A single observation draws only the accent endpoint dot: there is 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

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