ForecastCone
ForecastCone draws history as a solid line and the forecast as prediction bands that widen over the horizon.
- encodes
- prediction-band extent widening over the horizon
- precision
- medium — the widening itself is the message
- nodes
- ≤ 8
Q4 revenue is at 38 and the target is 45: ForecastCone shows the spread of where it lands. History is a solid line, and the forecast is a fan of prediction bands that widen over the horizon under a dashed median. Three of those choices are fixed rather than style options. At most two bands, 50 and 80, because a 95% band reads as false tail confidence at micro scale. The median is always dashed, so an estimate never renders as fact. And the cone must visibly widen: bands that narrow or stay flat are flagged, never quietly inflated.
Install
import { ForecastCone } from "@microcharts/react/forecast-cone";// history, forecast — real values under “Sample data” below<ForecastCone data={history} forecast={forecast} target={45} title="Q4 revenue" />Sample data
// weekly revenue ($M): 7 weeks of history, a 4-week widening forecastconst history = [30, 32, 31, 34, 36, 35, 38];const forecast = { mid: [39, 40, 41, 42], p80: [[36, 42], [35, 45], [34, 50], [33, 55]], p50: [[37, 41], [37, 43], [36, 46], [35, 49]],};Try it
When to use it
Use it for a "will we hit Q4?" forecast in a KPI card, a projection with its uncertainty inside a sentence, and band-vs-target landing reads. For a forecast with no uncertainty use Sparkline; for one estimate's spread, GradedBand.
Sizing
Variants
format also takes Intl.NumberFormatOptions — with a locale, the in-chart landing label and the accessible
summary's median, interval, and target numbers all follow that locale's own grouping and currency placement (the label
above reads "4.200 €", not "€4,200").
Edge cases
With no history the cone still draws from the first forecast point, and the accessible summary drops its "from N today" clause instead of naming a value that doesn't exist. A cone whose bands narrow instead of widen is an input error: uncertainty that doesn't grow with the horizon misrepresents confidence decay. It renders exactly as supplied, never auto-inflated, and logs a one-time dev warning so the mistake surfaces in development.
Four homes
Accessibility
The accessible name states the median, the horizon interval, and today's actual. With a target it adds whether the
band clears it: "Median forecast 42 by week 11 (80% between 33 and 55), from 38 today. The 80% band straddles the 50
target." The interactive entry is region-aware: history points announce a value, forecast points announce the median
and 80% interval.
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[] | Historical actuals. |
| forecast* | { mid: number[]; p80: [lo,hi][]; p50?: [lo,hi][] } | Median + prediction bands (at most 2: 50/80). |
| target | number | The landing reference the cone must clear (adds a clearance clause). |
| unit | string | Period noun for the summary (default "week"). |
| label | "landing" | "none" | Median endpoint value in a right gutter. |
| 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.