TraceFold
React trace fold chart — one rect per span by start, duration, and depth — a folded trace. Tiny accessible SVG microchart; RSC-safe static or /interactive.
TraceFold answers "where did the latency go — which spans, at which depth, on the path that actually determined the total?". Each span is a rect placed by its start time, sized by its duration, and stacked by its nesting depth. The critical path — the chain of spans that bound the total — is accented and everything else muted, so the answer to "which spans mattered" is immediate.
Install
import { TraceFold } from "@microcharts/react/trace-fold";// spans — real values under “Sample data” below<TraceFold data={spans} title="Request trace" />Sample data
const spans = [ { label: "request", start: 0, duration: 214, depth: 0 }, { label: "db.query", start: 10, duration: 86, depth: 1, parent: 0 }, { label: "auth", start: 0, duration: 8, depth: 1, parent: 0 }, { label: "render", start: 96, duration: 60, depth: 1, parent: 0 }, { label: "serialize", start: 156, duration: 40, depth: 1, parent: 0 }, { label: "index-scan", start: 12, duration: 70, depth: 2, parent: 1 }, { label: "decode", start: 82, duration: 12, depth: 2, parent: 1 }, { label: "log", start: 200, duration: 14, depth: 1, parent: 0 }, { label: "gc", start: 90, duration: 5, depth: 2, parent: 1 },];Try it
When to use it
- Good for — request traces, flame charts, p95-exemplar latency breakdowns.
- Avoid for — a single duration (Bullet) or a time series (Sparkline).
Sizing
Variants
format also takes Intl.NumberFormatOptions — with a locale, the accessible summary's numbers follow that locale's
own grouping and decimal marks ("14.868 ms" in German, not "14,868 ms"). In-rect text stays the plain span label either
way; only the announced numbers are localized.
Edge cases
Four homes
Why this default
Accenting the critical path because "which spans mattered" is the question a uniform flame strip doesn't answer — the eye goes straight to the chain that set the total. Widths are durations on one linear shared time scale, never per-row normalized, so a wide span is genuinely a slow span. The only documented width distortion is a one-unit floor for zero-duration spans, and the critical-path walk is deterministic (ties resolve to the earliest start).
Accessibility
The accessible name names the biggest span and its path status — "4 spans over 214 ms; longest db.query (86 ms) on the critical path." The interactive entry roves spans within a depth with ←/→ and between depths with ↑/↓, announcing each span's duration, share of the total, depth, and whether it is on the critical path.
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* | Span[] | Flat span list; parent = index. |
| emphasis | "critical" | "none" | Mute non-critical spans, or uniform. |
| labels | boolean | Width-gated in-rect labels. |
| 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
PhaseTrace
React phase trace chart — cyclic phase as a compact trajectory on a shared ring. Tiny accessible SVG microchart; RSC-safe static or /interactive.
TapeGauge
React tape gauge chart — a linear tape reading — not a circular speedometer. Tiny accessible SVG microchart; RSC-safe static or /interactive.