Skip to main content

BandChart

A filled envelope between two columns — a variance or confidence band. Pair it with a centre line for the classic percentile fan.

src/examples/gallery-band.tsx
import {
BandChart,
ChartContainer,
ChartRow,
Layers,
LineChart,
YAxis,
} from '@pond-ts/charts';
import { useSiteChartTheme } from '@site/src/theme/useSiteChartTheme';
import { latencyPercentileBand } from './lib/gallery-fixtures';

/** Variance band: a rolling p5–p95 latency envelope with the p50 centreline
* — two nested bands (`outer`/`inner`) plus a line, the shape a
* `rollingByColumn` percentile pass produces. */
export default function GalleryBand({ width }: { width: number }) {
const theme = useSiteChartTheme();
const series = latencyPercentileBand();

return (
<ChartContainer range={series.timeRange()} width={width} theme={theme}>
<ChartRow height={220}>
<YAxis id="ms" side="right" label="ms" format=",.0f" width={44} />
<Layers>
<BandChart
series={series}
lower="p5"
upper="p95"
as="outer"
axis="ms"
/>
<BandChart
series={series}
lower="p25"
upper="p75"
as="inner"
axis="ms"
/>
<LineChart series={series} column="p50" axis="ms" />
</Layers>
</ChartRow>
</ChartContainer>
);
}

Data contract

Takes a TimeSeries or ValueSeries and two fixed columns, lower and upper (typically a rollingByColumn percentile pass — p25 / p75). A sample fills only where both edges are finite. Adapter: bandFromTimeSeries(series, lower, upper) / bandFromValueSeries.

Props

PropTypeDefaultPurpose
seriesTimeSeries | ValueSeries— (req)The source series.
lowerstring— (req)Column for the band's lower edge.
upperstring— (req)Column for the band's upper edge.
asstring'default'Style role → theme.band[as].
axisstringrow defaultWhich <YAxis id> to scale against.
curveCurve'linear'Both edges drawn with this curve.

Variants

  • curve — prefer a symmetric curve ('natural' / 'basis') for a sparse envelope; 'monotone' smooths the two edges asymmetrically.
  • Two-tone spread — not a prop: compose a wider outer band, then a narrower inner one, then a line on top (what the hero above does).

Interaction & theming

  • Cursor: the readout shows both edge values (labelled by column name), in the band's fill colour; nothing where either edge is non-finite.
  • Selection: not selectable.
  • Theming: the theme.band slot (BandStyle = { fill, opacity }); default roles default / outer / inner.

Cautions

  • A band always breaks on a gap — a gap on either edge leaves no fill or readout there; it never bridges.
  • No baseline — a band is the region between two edges, not a fill to a floor (that's AreaChart).

See also

  • AreaChart — a fill to a baseline, not between two edges.
  • Storybook: Charts/BandChartRollingPercentiles, TwoTone, WithGap.
  • The generated API reference — the full BandChartProps type.