Horizon
React horizon chart — banded horizon encoding for dense magnitude over time. Tiny accessible SVG microchart; RSC-safe static or /interactive.
Horizon answers "what happened across this wide-range series — in a 14-pixel row?" The series is cut into bands and folded: layer opacity carries magnitude, so extremes stay visible at heights where a sparkline would flatten into noise.
How to read it — every band rises from the row's bottom edge, positive or negative; darker means farther from the baseline, not which direction. Above-baseline values shade in the accent color, below-baseline in the negative color, so direction is never color-alone even though both fold upward the same way.
Install
import { Horizon } from "@microcharts/react/horizon";// cpuLoad — real values under “Sample data” below<Horizon data={cpuLoad} title="Cluster load" />Sample data
const cpuLoad = [ 2, 5, 9, 14, 22, 31, 26, 18, 12, 24, 38, 45, 41, 30, 19, 11, 6, 3, 8, 16, 27, 35, 29, 20,];Try it
When to use it
- Good for — dense monitoring rows (dozens stacked), wide-range series in tight cells.
- Avoid for — first-glance audiences (folding needs a key), or a few rows with room (Sparkline).
Sizing
Variants
format also takes Intl.NumberFormatOptions — with a locale, the accessible summary's range and last-value numbers
follow that locale's own grouping ("4.500" in German, not "4,500"). The interactive readout's per-point values localize
the same way; the folded geometry never changes.
Edge cases
Negative values take the negative token and fold from the same bottom edge as positive values (the default
mode="mirror") — both directions get darker as they move away from the baseline, so "denser" always means "farther
from typical," never "which sign." Identical values across the whole row still render as a solid block rather than
vanishing, keeping "flat" visibly distinct from "no data."
Four homes
Why this default
Two folds is the default because it needs no training to read approximately; three folds trade learnability for density
and should be reserved for ranges that genuinely span them. The baseline is authored, never inferred — a fold origin
is a claim about what "normal" means.
Accessibility
The accessible name reads the unfolded series — "Trending up 900%. Range 2 to 45. Last value 20." — so screen-reader users get the true values, not the folded geometry. The interactive readout announces unfolded values per point.
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 | null)[] | Series over time. |
| folds | 2 | 3 | Band count — 3 only when the range genuinely spans it. |
| mode | "mirror" | "offset" | Mirror flips negatives upward (denser); offset keeps up/down. |
| baseline | number | Fold origin (e.g. a target level) — authored, never inferred. |
| 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
Ohlc
React OHLC chart — per-period open–high–low–close in a table cell, never averaged. Tiny accessible SVG microchart; RSC-safe static or /interactive.
CalendarStrip
React calendar strip chart — recent weeks day-by-day with real calendar position. Tiny accessible SVG microchart; RSC-safe static or /interactive.