BarChart
Bar chart with vertical/horizontal orientation, grouped or stacked modes, and multi-series support.
Category: chart · WCAG 2.1-AA · chart, bar, data-viz
Variants
- grouped
- stacked
- percent
Props
| Prop | Type | Default | Description |
|---|---|---|---|
series | BarChartSeries<Datum>[] | — | Series array. Each series accepts an optional `color` (any CSS color) overriding the positional palette for that series/stacked layer. |
x | (d: Datum) => string | — | Accessor returning the **category label** for a datum. BarChart uses a categorical **band** scale, so `x` returns a `string` — this differs from LineChart/AreaChart, whose `x` returns `number | Date` for a continuous/time scale. For a time-based bar chart, format the date to a label in the accessor (e.g. `x={(d) => d.day.toLocaleDateString()}`). For continuous or time-series data, prefer LineChart/AreaChart. |
y | (d: Datum) => number | — | Accessor returning the numeric value for a datum, applied to every series unless a series sets its own `y`. One category (x) domain per chart; give each series a `y` to plot different fields from one shared data row. |
title | string | — | Title text for the component. |
description | string | — | Supporting description text. |
orientation | 'vertical' | 'horizontal' | vertical | Layout orientation of the component. |
mode | 'grouped' | 'stacked' | 'percent' | grouped | 'percent' stacks each category and normalizes it to 100%. |
width | number | — | Fixed SVG width in px. ⚠ **Omit for a responsive chart** — the chart fills and tracks its container via a ResizeObserver; there is no correct pixel number in a responsive grid. A fixed width is clamped to the container (max-inline-size: 100%) so it can never overflow its card, but it also stops the chart growing. `useChartSize` is NOT needed for this — charts call it internally. |
height | number | 300 | SVG height in px. Unlike `width`, height does NOT track the container — this is the knob you set to change the chart's aspect. |
xTicks | number | — | Approximate number of ticks on the x-axis. |
yTicks | number | 5 | Approximate number of ticks on the y-axis. |
xLabelEvery | number | — | Show every Nth category label (always the last) to thin a crowded x-axis. |
legend | boolean | — | Whether to show the legend. |
tooltip | boolean | — | Whether to show tooltips on hover. |
tooltipFormat | (p: ChartPoint) => string | — | Custom tooltip formatter. The stacked default lists "label · total" + each non-zero layer in its color. |
className | string | — | Additional CSS class names merged onto the root element. |
plain | boolean | false | Marks only — no axes, grid lines, or legend. For micro/inline charts. |
annotations | Annotation[] | — | Reference lines, shaded bands, and markers drawn over the plot (e.g. a target/threshold line). |
labels | boolean | { format?: (v: number) => string; position?: string } | — | Print each value as a label on the mark (collision-aware, decorative/aria-hidden). |
onSelect | (point: ChartPoint) => void | — | Fired when a point is clicked or activated (Enter/Space) — for drill-down. |
fill | 'solid' | 'gradient' | 'pattern' | solid | Bar fill style — solid, a gradient, or a pattern. |
patternKind | 'dots' | 'lines' | 'cross' | — | Pattern motif when fill="pattern". |
Design tokens
--cascivo-chart-1--cascivo-chart-2--cascivo-chart-3--cascivo-chart-4--cascivo-chart-5--cascivo-chart-6--cascivo-chart-7--cascivo-chart-8
When to use
- Comparing discrete categorical values across groups
- Showing grouped or stacked multi-series data per category
When not to use
- Showing trends over continuous time — use LineChart
- Part-of-whole proportions — use PieChart for ≤5 categories
Examples
Basic bar chart
import { BarChart } from '@cascivo/charts'
const series = [{ id: 'a', label: 'Sales', data: [{x:'Jan',y:100},{x:'Feb',y:150}] }]
<BarChart series={series} x={d => d.x} y={d => d.y} title="Sales" />Date-based categories (format the Date in the accessor)
BarChart's x is a category string, not a Date. When your data is date-keyed, format the Date to a label string inside the x accessor — do NOT return the Date itself (that is a type error; only LineChart/AreaChart take a Date x).
import { BarChart } from '@cascivo/charts'
const series = [{ id: 'signups', label: 'Signups', data: [
{ day: new Date('2026-07-01'), count: 12 },
{ day: new Date('2026-07-02'), count: 18 },
] }]
<BarChart
series={series}
x={(d) => d.day.toLocaleDateString(undefined, { month: 'short', day: 'numeric' })}
y={(d) => d.count}
xLabelEvery={2}
title="Daily signups"
/>Stacked bar from row-oriented data
import { BarChart, toStackedSeries } from '@cascivo/charts'
// Pivot { label, segments[] } rows into series + x/y. Per-segment color is preserved.
const rows = [
{ label: 'Mon', segments: [
{ key: 'Done', value: 5, color: 'var(--cascivo-color-success)' },
{ key: 'Blocked', value: 2, color: 'var(--cascivo-color-destructive)' },
] },
{ label: 'Tue', segments: [
{ key: 'Done', value: 8, color: 'var(--cascivo-color-success)' },
{ key: 'Blocked', value: 1, color: 'var(--cascivo-color-destructive)' },
] },
]
// Tooltip shows "Mon · 7" then each non-zero layer in its color.
<BarChart mode="stacked" tooltip {...toStackedSeries(rows)} title="Throughput" />