Skip to content
microcharts
ReferenceDecisionPercentileTrace

PercentileTrace

React percentile trace chart — percentile fan or ribbon over ordered samples. Tiny accessible SVG microchart; RSC-safe static or /interactive.

PercentileTrace answers "is this entity's standing rising or slipping inside the pack?". It traces one percentile rank over time on a scale locked to 0–100. Because the axis is rank, the population is constant by definition — the middle-half (p25–75) and near-full (p5–95) bands are fixed fields, not estimates — so the only line on the chart is the entity itself, drifting through a known landscape.

PercentileTrace
interactive · 5.33 kB · static · 2.88 kB

Install

Import & usereact/percentile-trace
import { PercentileTrace } from "@microcharts/react/percentile-trace";// ranks — real values under “Sample data” below<PercentileTrace data={ranks} title="Standing" />
Sample data
// a weekly standing that drifts up from the middle half into the top bandconst ranks = [40, 46, 52, 58, 63, 68, 72, 76, 79, 81];
Needs package + stylesheetSet up with AI

Try it

When to use it

  • Good for — one player's or product's rank drifting over time, whether a standing has crossed into the top or bottom of the pack, a percentile KPI where the population context matters.
  • Avoid for — a raw value over time (Sparkline) or one absolute number vs a target (Bullet / Delta).

Sizing

Variants

showBands, and no bands

The endpoint dot carries valence: by default a rising standing is good, so it turns positive; set positive="down" when slipping down the pack is the win (a support ticket's backlog rank, say). The line already encodes the direction, so the color is only a redundant cue — never the sole signal.

positive='down'

Edge cases

one reading
out-of-range clamp
locale

A single reading is a lone endpoint with no line to draw — it still reports its standing and holds the accessible-name contract. Ranks outside 0–100 are clamped to the axis (a value of 102 reads as p100) and warn once in development. With a locale, the percentile label and every announced number follow that locale's own formatting — de-DE renders p81,5 with a comma.

Four homes

Why this default

The full 0–100 axis with fixed bands, because a percentile is a standing within a population — truncating the axis would hide how much headroom or floor is left, and re-estimating the bands from the single traced series would be a fiction. The middle-half and near-full fields are exact by construction, so the chart shows one honest line over a landscape you can trust, never a thicket of competing series.

Accessibility

The accessible name states the current percentile, the change from the first reading, and how the standing moved relative to the middle half — "p81 now, up 41 points from the first reading; moved above the middle half." The interactive entry steps the readings and announces each one's percentile.

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*number[]Percentile ranks 0–100, one per reading; out-of-range values are clamped.
showBandsbooleanDraw the fixed p25–75 and p5–95 population fields (default true).
positive"up" | "down"Which direction is good — colors the endpoint dot (default up).
label"last" | "none"Final percentile in a right gutter.
unitstringinteractiveReading noun for the interactive announcement (default 'step').
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