Bar Chart V2

Basic

A grouped bar chart rendered as static SVG at build time, with no JavaScript. The chart renders at its design size, shrinks to fit narrow containers, and never scales up. Colours come from a validated categorical palette with dedicated dark theme steps. Hover a bar for its value, or open View data for the table.

Series a
Series b
020406080One, Series a: 30One, Series b: 45Two, Series a: 52Two, Series b: 38Three, Series a: 41Three, Series b: 60Four, Series a: 74Four, Series b: 55OneTwoThreeFourValueGroup
<BarChartV2
label="Two series across four groups"
xLabel="Group"
yLabel="Value"
data={[
{ label: 'One', values: [30, 45] },
{ label: 'Two', values: [52, 38] },
{ label: 'Three', values: [41, 60] },
{ label: 'Four', values: [74, 55] },
]}
series={[{ label: 'Series a' }, { label: 'Series b' }]}
/>

Single series

With one series the legend is omitted and the label prop names the chart.

05001,0001,5002,0002,5003,0003,500One, Series a: 1,200Two, Series a: 2,400Three, Series a: 1,800Four, Series a: 3,100Five, Series a: 2,650OneTwoThreeFourFive
<BarChartV2
label="A single series"
data={[
{ label: 'One', values: [1200] },
{ label: 'Two', values: [2400] },
{ label: 'Three', values: [1800] },
{ label: 'Four', values: [3100] },
{ label: 'Five', values: [2650] },
]}
series={[{ label: 'Series a' }]}
height={240}
/>

Many groups

Twenty groups in a single series. Bars share the group scale evenly, and group labels thin to every nth automatically when there is not enough room for all of them.

0204060801001, Series a: 452, Series a: 603, Series a: 754, Series a: 865, Series a: 956, Series a: 807, Series a: 818, Series a: 789, Series a: 7310, Series a: 6611, Series a: 3812, Series a: 3113, Series a: 2714, Series a: 2415, Series a: 2616, Series a: 1117, Series a: 2118, Series a: 3319, Series a: 4720, Series a: 631234567891011121314151617181920
<BarChartV2
label="Twenty bars in a single series"
data={Array.from({ length: 20 }, (_, index) => ({
label: String(index + 1),
values: [Math.round(45 + 35 * Math.sin(index / 3) + (index % 5) * 4)],
}))}
series={[{ label: 'Series a' }]}
/>

Colour with many bars

Colour identifies series, so a chart with many bars gets colour from having several series. Three series across twenty groups renders sixty coloured bars, with the legend and gaps carrying identity at small sizes. The built-in palette covers eight series and further series receive generated evenly spaced hues.

Series a
Series b
Series c
0102030405060701, Series a: 401, Series b: 581, Series c: 152, Series a: 502, Series b: 542, Series c: 133, Series a: 593, Series b: 503, Series c: 114, Series a: 654, Series b: 454, Series c: 105, Series a: 695, Series b: 395, Series c: 106, Series a: 706, Series b: 326, Series c: 117, Series a: 677, Series b: 267, Series c: 128, Series a: 628, Series b: 218, Series c: 159, Series a: 549, Series b: 169, Series c: 1710, Series a: 4410, Series b: 1310, Series c: 2111, Series a: 3411, Series b: 1111, Series c: 2412, Series a: 2512, Series b: 1012, Series c: 2813, Series a: 1713, Series b: 1113, Series c: 3214, Series a: 1214, Series b: 1414, Series c: 3615, Series a: 1015, Series b: 1715, Series c: 4016, Series a: 1116, Series b: 2216, Series c: 4317, Series a: 1617, Series b: 2817, Series c: 4618, Series a: 2318, Series b: 3418, Series c: 4819, Series a: 3219, Series b: 4019, Series c: 4920, Series a: 4220, Series b: 4620, Series c: 501234567891011121314151617181920
<BarChartV2
label="Three series across twenty groups"
data={Array.from({ length: 20 }, (_, index) => ({
label: String(index + 1),
values: [
Math.round(40 + 30 * Math.sin(index / 3)),
Math.round(35 + 25 * Math.sin(index / 4 + 2)),
Math.round(30 + 20 * Math.sin(index / 5 + 4)),
],
}))}
series={[{ label: 'Series a' }, { label: 'Series b' }, { label: 'Series c' }]}
/>

Custom colours

Each series accepts a color override, and the palette prop replaces the whole default palette. Overrides apply to every theme, so check their contrast on the surfaces you use.

Series a
Series b
Series c
010203040One, Series a: 18One, Series b: 31One, Series c: 24Two, Series a: 26Two, Series b: 22Two, Series c: 35Three, Series a: 33Three, Series b: 40Three, Series c: 28OneTwoThree
<BarChartV2
label="Custom series colours"
data={[
{ label: 'One', values: [18, 31, 24] },
{ label: 'Two', values: [26, 22, 35] },
{ label: 'Three', values: [33, 40, 28] },
]}
series={[
{ label: 'Series a' },
{ label: 'Series b', color: '#0c6b6b' },
{ label: 'Series c' },
]}
/>

Horizontal

orientation renders the bars horizontally: groups run down the left edge and the value axis sits along the bottom. Long group labels truncate with an ellipsis instead of tilting.

Horizontal bars
Series a
Series b
0102030405060One, Series a: 64One, Series b: 41Two, Series a: 38Two, Series b: 52Three, Series a: 55Three, Series b: 30Four, Series a: 27Four, Series b: 45OneTwoThreeFourValue
<BarChartV2
title="Horizontal bars"
orientation="horizontal"
xLabel="Value"
data={[
{ label: 'One', values: [64, 41] },
{ label: 'Two', values: [38, 52] },
{ label: 'Three', values: [55, 30] },
{ label: 'Four', values: [27, 45] },
]}
series={[{ label: 'Series a' }, { label: 'Series b' }]}
height={280}
/>

Stacked

stacked places the series on top of one another within each group, so the bar length shows the group total. The value axis scales to the largest total.

Stacked columns
Series a
Series b
Series c
020406080One, Series a: 22One, Series b: 34One, Series c: 18Two, Series a: 30Two, Series b: 16Two, Series c: 25Three, Series a: 17Three, Series b: 28Three, Series c: 21Four, Series a: 26Four, Series b: 19Four, Series c: 32OneTwoThreeFour
<BarChartV2
title="Stacked columns"
stacked
data={[
{ label: 'One', values: [22, 34, 18] },
{ label: 'Two', values: [30, 16, 25] },
{ label: 'Three', values: [17, 28, 21] },
{ label: 'Four', values: [26, 19, 32] },
]}
series={[{ label: 'Series a' }, { label: 'Series b' }, { label: 'Series c' }]}
/>

Stacked horizontal

Stacking and orientation compose. Each segment keeps its own hover value and data attributes.

Stacked horizontal bars
Series a
Series b
Series c
020406080One, Series a: 22One, Series b: 34One, Series c: 18Two, Series a: 30Two, Series b: 16Two, Series c: 25Three, Series a: 17Three, Series b: 28Three, Series c: 21Four, Series a: 26Four, Series b: 19Four, Series c: 32OneTwoThreeFourValue
<BarChartV2
title="Stacked horizontal bars"
stacked
orientation="horizontal"
xLabel="Value"
data={[
{ label: 'One', values: [22, 34, 18] },
{ label: 'Two', values: [30, 16, 25] },
{ label: 'Three', values: [17, 28, 21] },
{ label: 'Four', values: [26, 19, 32] },
]}
series={[{ label: 'Series a' }, { label: 'Series b' }, { label: 'Series c' }]}
height={240}
/>

Colour scale

colorScale generates one colour per series by interpolating between its anchors in OKLCH. Explicit series colours and the palette prop still take precedence when set.

Colour scale across six series
Series a
Series b
Series c
Series d
Series e
Series f
020406080One, Series a: 12One, Series b: 18One, Series c: 9One, Series d: 14One, Series e: 7One, Series f: 11Two, Series a: 15Two, Series b: 11Two, Series c: 13Two, Series d: 8Two, Series e: 12Two, Series f: 9Three, Series a: 9Three, Series b: 14Three, Series c: 16Three, Series d: 11Three, Series e: 8Three, Series f: 13Four, Series a: 13Four, Series b: 9Four, Series c: 11Four, Series d: 15Four, Series e: 10Four, Series f: 8OneTwoThreeFour
<BarChartV2
title="Colour scale across six series"
stacked
colorScale={['#1baf7a', '#4a3aa7']}
data={[
{ label: 'One', values: [12, 18, 9, 14, 7, 11] },
{ label: 'Two', values: [15, 11, 13, 8, 12, 9] },
{ label: 'Three', values: [9, 14, 16, 11, 8, 13] },
{ label: 'Four', values: [13, 9, 11, 15, 10, 8] },
]}
series={[
{ label: 'Series a' },
{ label: 'Series b' },
{ label: 'Series c' },
{ label: 'Series d' },
{ label: 'Series e' },
{ label: 'Series f' },
]}
/>

Title

The title prop renders a heading above the chart. It also becomes the accessible name, unless the label prop is set to override it.

Chart title
Series a
Series b
020406080One, Series a: 30One, Series b: 45Two, Series a: 52Two, Series b: 38Three, Series a: 41Three, Series b: 60Four, Series a: 74Four, Series b: 55OneTwoThreeFour
<BarChartV2
title="Chart title"
data={[
{ label: 'One', values: [30, 45] },
{ label: 'Two', values: [52, 38] },
{ label: 'Three', values: [41, 60] },
{ label: 'Four', values: [74, 55] },
]}
series={[{ label: 'Series a' }, { label: 'Series b' }]}
/>

Legend placement

The legend prop controls the key. auto shows it only for two or more series, top and bottom force its position, and hidden removes it.

020406080One, Series a: 30One, Series b: 45Two, Series a: 52Two, Series b: 38Three, Series a: 41Three, Series b: 60Four, Series a: 74Four, Series b: 55OneTwoThreeFour
Series a
Series b
<BarChartV2
label="Legend below the chart"
legend="bottom"
data={[
{ label: 'One', values: [30, 45] },
{ label: 'Two', values: [52, 38] },
{ label: 'Three', values: [41, 60] },
{ label: 'Four', values: [74, 55] },
]}
series={[{ label: 'Series a' }, { label: 'Series b' }]}
/>

Sparkline

Setting axes to false drops the ticks, labels, and baseline so their margins collapse, leaving just the bars. The same chart works across sizes, shown here from a tiny inline sparkline up to a larger block.

One, Series a: 12Two, Series a: 24Three, Series a: 18Four, Series a: 31Five, Series a: 26Six, Series a: 22Seven, Series a: 34
One, Series a: 12Two, Series a: 24Three, Series a: 18Four, Series a: 31Five, Series a: 26Six, Series a: 22Seven, Series a: 34
One, Series a: 12Two, Series a: 24Three, Series a: 18Four, Series a: 31Five, Series a: 26Six, Series a: 22Seven, Series a: 34
One, Series a: 12Two, Series a: 24Three, Series a: 18Four, Series a: 31Five, Series a: 26Six, Series a: 22Seven, Series a: 34
<Inline
space="large"
alignY="center">
{sizes.map((size) => (
<BarChartV2
label="Sparkline"
axes={false}
width={size.width}
height={size.height}
data={data}
series={series}
/>
))}
</Inline>

Months of the year

Twelve months in a single series, one value each. Group labels thin automatically if the chart is too narrow to fit all twelve.

020406080Jan, Series a: 42Feb, Series a: 38Mar, Series a: 55Apr, Series a: 61May, Series a: 58Jun, Series a: 72Jul, Series a: 80Aug, Series a: 76Sep, Series a: 64Oct, Series a: 59Nov, Series a: 48Dec, Series a: 45JanFebMarAprMayJunJulAugSepOctNovDecValueMonth
<BarChartV2
label="Values by month"
xLabel="Month"
yLabel="Value"
data={data}
series={[{ label: 'Series a' }]}
/>

Full month names

Full month names are too wide to sit flat, so every label tilts to -45 degrees. Tilted labels run parallel and never collide, so they only truncate with an ellipsis when one would hang past about a third of the chart height.

020406080January, Series a: 42February, Series a: 38March, Series a: 55April, Series a: 61May, Series a: 58June, Series a: 72July, Series a: 80August, Series a: 76September, Series a: 64October, Series a: 59November, Series a: 48Decemberrr rrrrrrrrrr fff, Series a: 45JanuaryFebruaryMarchAprilMayJuneJulyAugustSeptemberOctoberNovemberDecemberrr rrrrrrr…ValueMonth
<BarChartV2
label="Values by month"
xLabel="Month"
yLabel="Value"
data={data}
series={[{ label: 'Series a' }]}
/>

Build status

Custom colours turn two series into a red and green build tracker: passed builds in green, failed in red. Shown as a full chart and a compact axis-less variant.

Build status
Passed
Failed
05101520Mon, Passed: 22Mon, Failed: 1Tue, Passed: 19Wed, Passed: 24Wed, Failed: 4Thu, Passed: 21Fri, Passed: 16Fri, Failed: 6Sat, Passed: 9Sat, Failed: 1Sun, Passed: 12MonTueWedThuFriSatSunBuildsDay
Passed
Failed
Mon, Passed: 22Mon, Failed: 1Tue, Passed: 19Wed, Passed: 24Wed, Failed: 4Thu, Passed: 21Fri, Passed: 16Fri, Failed: 6Sat, Passed: 9Sat, Failed: 1Sun, Passed: 12
<Stack space="large">
<BarChartV2
title="Build status"
xLabel="Day"
yLabel="Builds"
data={data}
series={series}
/>
<BarChartV2
label="Build status sparkline"
axes={false}
width={280}
height={80}
data={data}
series={series}
/>
</Stack>