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
| Prop | Type | Default | Purpose |
|---|---|---|---|
series | TimeSeries | ValueSeries | — (req) | The source series. |
lower | string | — (req) | Column for the band's lower edge. |
upper | string | — (req) | Column for the band's upper edge. |
as | string | 'default' | Style role → theme.band[as]. |
axis | string | row default | Which <YAxis id> to scale against. |
curve | Curve | '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
outerband, then a narrowerinnerone, 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.bandslot (BandStyle={ fill, opacity }); default rolesdefault/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/BandChart—RollingPercentiles,TwoTone,WithGap. - The generated API reference — the full
BandChartPropstype.