EnsembleGhosts
React ensemble ghosts chart — faint ensemble paths with an emphasised median-like member. Tiny accessible SVG microchart; RSC-safe static or /interactive.
EnsembleGhosts answers "what could happen, across the simulated futures?". It draws a faint bundle of member paths with one emphasized representative — because a mean line hides that futures disagree in shape, not just endpoint. Ghost selection is fully deterministic (evenly spaced endpoint-rank quantiles), so the same input renders identically every time.
Install
import { EnsembleGhosts } from "@microcharts/react/ensemble-ghosts";// futures — real values under “Sample data” below<EnsembleGhosts data={futures} title="Simulated futures" />Sample data
// 24 simulated futures — a fan of walks with diverse shapesconst futures = Array.from({ length: 24 }, (_m, i) => Array.from({ length: 10 }, (_, t) => Math.round(40 + (i - 12) * 0.55 * t * 0.4 + 3 * Math.sin(i + t) + t * 0.5), ),);Try it
When to use it
- Good for — a KPI card that shows the futures, not the average; Monte-Carlo / simulation output where paths disagree in shape; showing that outcomes fan out.
- Avoid for — interval precision (ForecastCone) or a single path (Sparkline).
Sizing
Variants
Edge cases
With one member, there is no bundle to show — the chart draws that single path as the representative, and the summary
states its ending value rather than a spread. A member that contains a non-finite value (NaN, Infinity) is excluded
entirely from ghost selection and the median, not gapped mid-path — a dev-only console warning flags it, since a
partially invalid future usually means bad simulation output.
Four homes
Why this default
A few faint paths and one emphasized, because a mean line hides that futures disagree in shape, not just endpoint — two
ensembles can share an average and a final range while telling completely different stories along the way. The
emphasized path defaults to the real member closest to the pointwise median, so the representative is an outcome
that actually happened in the simulation, not a synthetic average of paths that never occurred (emphasis="median"
draws that synthetic path instead). Selection and emphasis are deterministic — nothing about this chart varies between
renders of the same data. label="end" (default) states the emphasized path's landing value in a right gutter; pass
label="none" to drop it.
The static frame is not a hypothetical-outcome plot. The loop — flipping through the members one at a time on hover — is the HOP, and it lives only in the interactive entry, gated on reduced motion with arrow-key stepping as the non-animated equivalent.
Accessibility
The accessible name states the endpoint spread and the typical path — "5 simulated paths end between 28 and 61; typical path ends near 50." The interactive entry flips through the members (the HOP loop) on hover; with reduced motion, ←/→ step them discretely, and each member is announced with its endpoint.
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* | number[][] | Ensemble members — 2–50 simulated paths. |
| ghosts | number | Rendered member count (deterministic endpoint-rank selection). Default 8, cap 12. |
| emphasis | "nearest-median" | "median" | number | A real median-like member, the synthetic median, or a pinned member. |
| endpoints | boolean | Ghost endpoint dots — makes the final-value spread countable. |
| label | "end" | "none" | Emphasised path endpoint in a right gutter (default end). |
| 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
ChangePoint
React change-point chart — regime breaks marked on a series with mean hairlines. Tiny accessible SVG microchart; RSC-safe static or /interactive.
CohortTriangle
React cohort triangle chart — retention by vintage × age as a shaded triangle heatmap. Tiny accessible SVG microchart; RSC-safe static or /interactive.