boxY summarizes raw observations into vertical boxplots. boxX transposes the same statistical and interaction semantics into horizontal boxplots. boxRows exposes their eager semantic preparation for reuse outside a mark.
import { boxY } from '@tanstack/charts/box'
boxY(rows, {
x: 'group',
y: 'value',
key: 'id',
fill: '#bfdbfe',
stroke: '#2563eb',
})The transform and both marks are also exported from @tanstack/charts and @tanstack/charts/universal.
function boxY<TDatum>(
source: Iterable<TDatum>,
options: BoxYOptions<TDatum>,
): ChartMark<BoxDatum<TDatum, InferredX>, InferredX, number>
function boxX<TDatum>(
source: Iterable<TDatum>,
options: BoxXOptions<TDatum>,
): ChartMark<BoxDatum<TDatum, InferredY>, number, InferredY>
function boxRows<TDatum>(
source: Iterable<TDatum>,
options: BoxRowsOptions<TDatum>,
): BoxDatum<TDatum, InferredCategory>[]boxY requires a categorical x channel and numeric y channel. boxX requires numeric x and categorical y.
For each non-null category, the mark:
Categories retain first-seen order. Outliers retain their global source order, including when category rows are interleaved. A category with no finite value is omitted. Singleton, two-value, and zero-IQR groups use the same rules rather than a separate fallback.
The mark composes a whisker link, interquartile bar, median tick, and outlier dots. Those native children remain renderer-neutral; the mark does not emit a custom SVG path.
Use boxRows when the same summary feeds multiple marks, a table, or application logic:
import { boxRows } from '@tanstack/charts/box'
const prepared = boxRows(rows, {
category: 'group',
value: 'measurement',
})category and value use the standard TransformValue contract. A field name reads that field. An accessor receives { datum, index, data }. Preparation is eager, does not mutate source rows, and returns all summary rows followed by outliers in global source order. The result contains semantic data and lineage only; child-mark identity remains internal to boxX and boxY.
| Option | Type | Default | Meaning |
|---|---|---|---|
| id | string | Layer-derived | Stable parent mark ID |
| x | boxY: Channel<TDatum, ChartValue?>; boxX: Channel<TDatum, number?> | Required | Category for boxY; finite observation for boxX |
| y | boxY: Channel<TDatum, number?>; boxX: Channel<TDatum, ChartValue?> | Required | Finite observation for boxY; category for boxX |
| key | Channel<TDatum, ChartKey> | Inferred | Stable raw-observation identity, including duplicate outliers |
| fill | string | #ccc | Interquartile box fill |
| fillOpacity | number | SVG default | Interquartile box fill opacity |
| stroke | string | currentColor | Whisker, median, and outlier stroke |
| strokeOpacity | number | SVG default | Whisker, median, and outlier stroke opacity |
| strokeWidth | number | Per child | Overrides whisker, median, and outlier widths together |
| inset | number | 0 | Pixels removed from both categorical edges of box and median |
| r | number | 3 | Outlier radius in pixels |
| motion | ChartMotionDefinition<BoxDatum<...>> | None | Motion for derived summary and outlier data |
The orientation determines the exact x and y channel types; the combined row above is shorthand. Use BoxYOptions or BoxXOptions when naming an options object separately.
The chart datum is a discriminated union:
type BoxDatum<TDatum, TCategory> =
| {
kind: 'summary'
category: TCategory
q1: number
median: number
q3: number
whiskerLow: number
whiskerHigh: number
count: number
source: readonly TDatum[]
sourceIndexes: readonly number[]
}
| {
kind: 'outlier'
category: TCategory
value: number
source: readonly [TDatum]
sourceIndexes: readonly [number]
}Use datum.kind in tooltip, motion, or selection code. Summary lineage contains every finite contributing observation in source order. An outlier retains its exact source row and index.
The public type surface includes BoxDatum, BoxYDatum, BoxXDatum, BoxSummaryDatum, BoxOutlierDatum, BoxRowsOptions, BoxYOptions, and BoxXOptions.
Each category contributes one summary point owned by the box body and anchored at the median. The whisker and median tick are decorative. Each outlier dot contributes its own point and raw-row lineage. This keeps pointer, keyboard, tooltip, and motion behavior from receiving duplicate summary targets for the same category.
Supply key when observation identity matters across updates or when duplicate outlier values can occur in one category.