Skip to content
microcharts
ReferenceFrontierFoldedDayBand

FoldedDayBand

React folded day-band chart — intraday band folded so days stack for comparison. Tiny accessible SVG microchart; RSC-safe static or /interactive.

FoldedDayBand answers "what does a typical period look like — and is the current one typical?". It folds many days (or weeks, or any cycle) onto a single period axis and shows the median with 25–75 and 5–95 percentile envelopes. Drop in a today overlay and the chart answers the second question: is right now inside the usual band, or an outlier?

FoldedDayBand
interactive · 4.8 kB · static · 2.51 kB

Install

Import & usereact/folded-day-band
import { FoldedDayBand } from "@microcharts/react/folded-day-band";// observations, today — real values under “Sample data” below<FoldedDayBand data={observations} today={today} title="Typical day" />
Sample data
const observations = Array.from({ length: 14 }, (_d, d) =>  Array.from({ length: 24 }, (_h, h) => ({    t: d * 24 + h,    value: Math.round(40 + 42 * Math.max(0, 1 - Math.abs(h - 14) / 10) + Math.sin(d + h) * 8),  })),).flat();const today = Array.from({ length: 24 }, (_h, h) => ({  t: h,  value: Math.round(40 + 42 * Math.max(0, 1 - Math.abs(h - 14) / 10) + 14),}));
Needs package + stylesheetSet up with AI

Try it

When to use it

  • Good for — typical-day traffic or load profiles, on-call or energy capacity planning.
  • Avoid for — a raw time series (Sparkline) or a single period with nothing to fold.

Sizing

Variants

one band vs locale

format also takes Intl.NumberFormatOptions — with a locale, the accessible summary's fold position and peak value follow that locale's own decimal mark ("14,0" in German, not "14.0"). The band and median line themselves don't change shape; only the announced numbers are localized.

Edge cases

single observation
all-equal → flat band

A single observation reports a real accessible name (median and peak both equal that one value) but has no width to fold across, so nothing visibly paints — the chart is accessible-first even when there's too little data to draw. Identical values across every bin still render as a flat line, distinct from an empty data array, which renders nothing and announces "No data."

Four homes

Why this default

Two envelopes plus a median is the typical-day grammar that clinical glucose profiles standardized on. The envelopes come from real per-bin quantiles — never smoothed across bins into a shape the data doesn't support — and the outer boundary fades so 5–95 doesn't read as a hard limit. When a bin has too few observations the band collapses to the median there rather than inventing a width.

Accessibility

The accessible name reports the peak — "Median peaks at 14 (82.5)." The interactive entry roves the folded axis with ←/→, announcing the median and middle-half at each position.

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

PropTypeNotes
data*{ t, value }[]Raw observations across many periods.
periodnumberFold length (168 folds a week).
today{ t, value }[]The current period overlaid.
percentiles[number, number][]Percentile pairs, outermost last.
binsnumberFold-axis resolution (default 24).
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