Skip to main content

BoxPlot

Box-and-whisker per bucket, drawn from pre-computed quantile columns. For a distribution over time (a latency percentile fan) or over a value axis.

src/examples/gallery-boxplot.tsx
import {
BoxPlot,
ChartContainer,
ChartRow,
Layers,
YAxis,
LineCursor,
} from '@pond-ts/charts';
import { useSiteChartTheme } from '@site/src/theme/useSiteChartTheme';
import { hourlyLatencyBoxes, hourlyLatencyRange } from './lib/gallery-fixtures';

/** Latency percentiles: hourly box-and-whisker buckets from five
* pre-computed quantile columns — the shape a percentile rollup produces. */
export default function GalleryBoxplot({ width }: { width: number }) {
const theme = useSiteChartTheme();
const series = hourlyLatencyBoxes();

return (
<ChartContainer range={hourlyLatencyRange()} width={width} theme={theme}>
<LineCursor />
<ChartRow height={220}>
<YAxis id="ms" side="right" label="ms" format=",.0f" width={44} />
<Layers>
<BoxPlot
series={series}
lower="p5"
q1="p25"
median="p50"
q3="p75"
upper="p95"
axis="ms"
gap={10}
/>
</Layers>
</ChartRow>
</ChartContainer>
);
}

Data contract​

Takes a TimeSeries or ValueSeries whose columns are already the quantiles — the chart does not compute them (feed a rolling / aggregate percentile pass). lower and upper are required; q1 + q3 (both or neither) and median are optional. A full box is five columns; a range-only box is just lower / upper. The box's x-span is the interval key [begin, end) or neighbour spacing. View builder (for custom draw code): boxFromTimeSeries(series, { lower, q1, median, q3, upper }) / boxFromValueSeries.

Props​

PropTypeDefaultPurpose
seriesTimeSeries | ValueSeries— (req)The source series.
lowerstring— (req)Lower whisker column (e.g. p5 / min).
upperstring— (req)Upper whisker column (e.g. p95 / max).
q1string—Box bottom (Q1). Both-or-neither with q3.
q3string—Box top (Q3).
medianstring—Median line column; omit for no centre line.
asstring'default'Style role → theme.box[as].
axisstringrow defaultWhich <YAxis id> to scale against.
shape'whisker' | 'solid' | 'none''whisker'Box presentation (see variants).
showMedianbooleantrueDraw the median line (no-op without a median column).
gapnumber0Total horizontal inset px.
capWidthnumberhalf box widthWhisker cap width (whisker shape only).
offsetnumber0Pixel x-shift — only the draw shifts, not the readout (keep small).
idstring—Stable identity — gates selection + hover (click / pointer-over).

Variants​

  • shape — 'whisker' (default: stems + caps), 'solid' (candlestick look: outer bar + darker q1→q3 inner, no stems), 'none' (the q1→q3 box only).
  • Full box vs range-only — omit q1 + q3 for a min/max range box.
  • showMedian — hide the centre line even when a median column is present.

Interaction & theming​

  • Cursor: reads the box under the cursor (span containment). The flag cursor shows a single consolidated flag at the box top with every quantile in one row, each coloured to its piece. The crosshair snaps to the box: its vertical line lands on the box centre and its horizontal line on the quantile nearest the pointer, with that value on the y-axis pill. onSnap reports that quantile: its label is the quantile's column name, or "<as> q3" style when the box has an as.
  • Selection: id-gated — set id and a box is clickable (the same selected/onSelect, hovered/onHover contract Line/Scatter/Bar carry). A click anywhere in a box (body or whisker — a range-only bid→ask segment included) selects it via rect-containment; the selected box outlines, a hovered one lights fainter. key is the box's x (its span begin). Without id the box is display-only. Independent of the cursor.
  • Theming: the theme.box slot (BoxStyle with fill / stroke / median / whisker); the selection outline reuses stroke (no new token).

Cautions​

  • The chart doesn't compute quantiles — supply them from a percentile rollup.
  • q1 / q3 are both-or-neither — passing one throws.
  • Range-only + shape='none' draws nothing — use 'whisker' or 'solid'.
  • offset shifts only the draw, not the readout — keep it small.

See also​

  • Candlestick — the OHLC counterpart (supersedes shape='solid' for price bars).
  • Storybook: Charts/BoxPlot — Percentiles, Solid, WithGap, the vol-smile variants.
  • The API reference — the full BoxPlotProps type.