Revenue by region, votes by option, latency by endpoint: a bar chart over names. Group a series' layers side by side, stack them or show their shares, label the values, and keep the bars readable while categories come and go.
01 — GROUP THE LAYERS
On a category axis, one
BarSeries with several layers draws them side by side in each band, in layer order, colored from the theme palette. That is the default with stacking: 'off'. Two separate BarSeries still overlap.<ChartContainer axis={{ x: { type: 'category' } }}> <BarSeries data={[ { label: '2024', data: [{ x: 'Europe', value: 46 }, { x: 'Asia', value: 41 }] }, { label: '2025', data: [{ x: 'Europe', value: 49 }, { x: 'Asia', value: 47 }] }, ]} /></ChartContainer>02 — FIX THE ORDER
Bands follow the order the data first names them.
axis.x.categories puts the listed names first, in list order — also a name no series has data for yet, as an empty band. Names not in the list follow in first-seen order.<ChartContainer axis={{ x: { type: 'category', categories: ['Asia', 'Europe', 'Americas'] } }}>03 — LABEL THE VALUES
valueLabels writes each value just past the bar's end. A label wider than its bar is skipped. The text follows <YAxis format>; pass { format } to set it apart. The color is theme.bar.labelColor.<BarSeries data={layers} options={{ valueLabels: { format: (v) => `$${v}M` } }} />04 — STACK, OR SHOW SHARES
stacking: 'normal' draws one column per band, with the column total as its label. 'percent' draws each layer's share of the column, so every column fills 100%; it has no labels.<BarSeries data={layers} options={{ stacking: 'percent' }} />05 — NEGATIVE VALUES
A negative bar grows down from zero, rounds its lower end and hangs its label below. In a 100% stack a column splits by its absolute sum: +3 and −1 give +75% up and −25% down.
<BarSeries data={[{ label: '2025', data: [{ x: 'Asia', value: 6 }, { x: 'Americas', value: -6 }] }]} />06 — CATEGORIES THAT COME AND GO
Pass the new array. A category that leaves fades out in its own band, then the bands close up and the later bars slide over; one that comes back slides the others aside and fades in. Values that change ease to their new height. Hovering a band shades it and lists every layer in the tooltip.
const regions = away ? REGIONS.filter((r) => r !== 'Americas') : REGIONS; <BarSeries data={toLayers(REVENUE, regions)} />