TraceFold
TraceFold lays out trace spans by start, duration, and depth, and accents the critical path.
- encodes
- width = duration, x = start, row = depth; critical path accented
- precision
- high
- nodes
- 1 rect per span, cap 40
A request took 214 ms and you need to know which spans set that number. TraceFold draws one rect per span, placed by its start time, sized by its duration, and stacked by its nesting depth. Widths sit on one shared linear time scale, never normalized per row, so a wide span is a slow span. The critical path, the chain of spans that bound the total, is accented and every other span muted.
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
Use it for request traces, flame charts, and p95-exemplar latency breakdowns. For a single duration use Bullet; for a time series use Sparkline.
Sizing
Variants
emphasis="none" drops the accent when the nesting, not the latency, is what you are reading. The critical-path walk
itself is deterministic: ties resolve to the earliest start.
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
A zero-duration span keeps a one-unit floor so it stays visible. That is the only width distortion in the chart.
Four homes
Accessibility
The accessible name gives 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.