Skip to content
microcharts
ReferenceDecisionEnsembleGhosts

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
collection
Decision
Source

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.

EnsembleGhosts
interactive · 6.49 kB · static · 3.28 kB

Install

Import & usereact/ensemble-ghosts
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),  ),);
Needs package + stylesheetSet up with AI

Try it

Live playground
onActive
idle
  1. hover · rove · click…

Hover to flip through the futures one at a time (the HOP loop); with reduced motion, arrow keys step them instead — each member is announced.

ghosts · 8
emphasis
endpoints
label
readout
animate
import { EnsembleGhosts } from "@microcharts/react/ensemble-ghosts/interactive";// futures — real values under “Sample data” below<EnsembleGhosts  data={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),  ),);

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

endpoint dots (countable spread)
synthetic median path

Variants

endpoint dots + synthetic median

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

single member
locale

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

In a sentence

Simulated futures — 70% of paths finish above target.

In a table cell
Base70%
Upside42%
Downside88%
In a KPI card
Q4 revenue
70%paths above target
In a tab header
BaseUpsideDownside

Preview uses the public chart API only. When an interactive twin exists, it swaps in with the same props and no entrance motion - code samples stay on the static import. Placement recipes: Composition, Sizing.

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, press Escape, or press outside the chart. On touch, a tap pins and a drag scrubs.

Props

PropTypeNotes
data*number[][]Ensemble members — 2–50 simulated paths.
ghostsnumberRendered member count (deterministic endpoint-rank selection). Default 8, cap 12.
emphasis"nearest-median" | "median" | numberA real median-like member, the synthetic median, or a pinned member.
endpointsbooleanGhost endpoint dots — makes the final-value spread countable.
label"end" | "none"Emphasised path endpoint in a right gutter (default end).
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