EnsembleGhosts
EnsembleGhosts draws simulated paths as a faint bundle with one representative member emphasized.
- encodes
- path-bundle spread + one emphasized representative
- precision
- low
- nodes
- ≤ 14 at cap
EnsembleGhosts draws a faint bundle of member paths with one emphasized representative, so you can see where the
simulated futures disagree in shape and not only at the endpoint. Two ensembles can share an average and a final
range while running completely different routes to get there, which is what a mean line hides. The emphasized path
defaults to the real member closest to the pointwise median, so the representative is a path the simulation produced;
emphasis="median" draws the synthetic pointwise median instead. Ghost selection is 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
Use it for a KPI card that shows the futures rather than the average, for Monte-Carlo and simulation output where paths disagree in shape, and for showing that outcomes fan out. When you need interval precision, use ForecastCone; for a single path, use Sparkline.
Sizing
Variants
endpoints marks where each ghost lands. label="end" is the default and states the emphasized path's landing value in
a right gutter; label="none" drops it.
Edge cases
With one member there is no bundle to draw, so the chart renders that single path as the representative and the summary
states its ending value rather than a spread. A member containing a non-finite value (NaN, Infinity) is excluded
from ghost selection and from the median entirely, rather than gapped mid-path, and a dev-only console warning flags it:
a partially invalid future usually means bad simulation output.
Four homes
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 static frame is not a hypothetical-outcome plot. The HOP loop, which flips through the members one at a time on hover, lives only in the interactive entry; with reduced motion, ←/→ step the members discretely instead, and each one 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.