Bar Chart
Grouped bars across categorical buckets, color-tokened by series with shared Y domain.
Overview
BarChart is a recharts chart wired to Gremorie's design tokens through the shadcn chart primitive (ChartContainer) for categorical comparison. Pass tabular data, a serializable config mapping each value field to a label plus a color, and the xKey for the category field. ChartContainer injects each series color as var(--color-<key>), and recharts renders the cartesian grid, axis ticks, and one set of grouped rectangles per series. Pass stacked, horizontal, or showLabels to switch layouts.
Reach for BarChart when discrete buckets matter - revenue by product, errors by service, users by region. For ordered-domain trends prefer LineChart or AreaChart; for two numeric axes prefer ScatterChart.
Preview
Installation
bash npx gremorie@latest add rx-bar-chart bash pnpm dlx gremorie@latest add rx-bar-chart bash yarn dlx gremorie@latest add rx-bar-chart bash bunx --bun gremorie@latest add rx-bar-chart Usage
import { BarChart } from "@gremorie/rx-data";
import type { ChartConfig, ChartDatum } from "@gremorie/rx-data";
const data: ChartDatum[] = [
{ month: "Jan", desktop: 186, mobile: 80 },
{ month: "Feb", desktop: 305, mobile: 200 },
{ month: "Mar", desktop: 237, mobile: 120 },
{ month: "Apr", desktop: 73, mobile: 190 },
{ month: "May", desktop: 209, mobile: 130 },
{ month: "Jun", desktop: 214, mobile: 140 },
];
const config: ChartConfig = {
desktop: { label: "Desktop", color: "var(--chart-1)" },
mobile: { label: "Mobile", color: "var(--chart-2)" },
};
export function VisitsByMonth() {
return <BarChart data={data} config={config} xKey="month" />;
}Angular edition planned for a follow-up release; it mirrors this component's anatomy.
API
<BarChart>
The styled wrapper. Renders a ChartContainer div wrapping a recharts <BarChart> (with accessibilityLayer enabled): a cartesian grid, X and Y axes, and one <Bar> per series in config, each filled with var(--color-<key>).
| Prop | Type | Default | Description |
|---|---|---|---|
data | readonly ChartDatum[] | - | Tabular data. Each row is a record from string keys to numeric or category values. The column at xKey is the category; every key in config must exist on every row as a numeric value. For per-bar colors on a single series, give each row a fill (e.g. var(--chart-1)). |
config | ChartConfig | - | Maps each series key to { label, color }. The color is any CSS color or token, typically "var(--chart-1)" through "var(--chart-5)"; ChartContainer exposes it as var(--color-<key>). |
xKey | string | - | Name of the category field on each row. Drives the category axis ticks (X by default, Y when horizontal). |
stacked | boolean | false | Stack the series within each category instead of grouping them side by side. |
horizontal | boolean | false | Render horizontal bars (recharts layout="vertical"). |
showLabels | boolean | false | Draw the value as a label on top of (or beside) each bar. |
tooltip | boolean | true | Show the hover tooltip. |
radius | number | 8 | Corner radius of the bars. |
className | string | - | Merged onto the ChartContainer. The bundled style supplies a rounded card surface plus aspect ratio. |
Chart primitive exports
@gremorie/rx-data re-exports the shadcn chart primitive so you can compose custom charts. Wrap raw recharts (Bar, Area, Line, CartesianGrid, XAxis, YAxis) inside ChartContainer:
| Export | Role |
|---|---|
ChartContainer | Provides the chart context, the responsive frame, and injects --color-<key> CSS vars from config. |
ChartTooltip / ChartTooltipContent | Token-styled hover tooltip. |
ChartLegend / ChartLegendContent | Token-styled legend. |
useChart | Hook returning the active ChartConfig from context. |
Types
| Type | Shape |
|---|---|
ChartDatum | Record<string, string | number> & { fill?: string } - one row of chart data; the optional fill sets a per-bar color. |
ChartConfig | Record<string, { label?: ReactNode; color?: string }> - per-series label and color map. |
Composition
- Pick
xKey- the categorical column that becomes the bottom axis. - Author
configmapping each value field to a label and a token-driven color. recharts auto-sizes the Y domain to cover every series. - Pass
dataas an array of records. - For custom rendering (extra reference lines, a custom legend, mixed series), compose raw recharts inside
<ChartContainer>(see Composing with the chart primitive).
The chart auto-sizes to its parent via recharts' ResponsiveContainer, so the wrapping surface controls the width. The default class on the ChartContainer pins the chart to aspect-video.
Variations
Single series
<BarChart
data={data}
config={{ revenue: { label: 'Revenue', color: 'var(--chart-1)' } }}
xKey="region"
/>The default shape. Reach for a single bar series when comparing one metric across buckets.
Multi-series side by side
const config: ChartConfig = {
desktop: { label: 'Desktop', color: 'var(--chart-1)' },
mobile: { label: 'Mobile', color: 'var(--chart-2)' },
};
<BarChart data={data} config={config} xKey="month" />;For comparing two or three series within the same bucket. Bars from different series share the X tick by default; keep the series count short (two or three) before the bars get too thin to read.
Stacked, horizontal, and labels
Set stacked to stack series within each category, horizontal to swap the axes, or showLabels to draw a value on each bar:
<BarChart data={data} config={config} xKey="month" stacked />
<BarChart data={data} config={config} xKey="month" horizontal />
<BarChart data={data} config={config} xKey="month" showLabels />Per-bar colors
For a single-series chart, give each row its own fill to color bars categorically:
const data: ChartDatum[] = [
{ browser: 'Chrome', visitors: 275, fill: 'var(--chart-1)' },
{ browser: 'Safari', visitors: 200, fill: 'var(--chart-2)' },
{ browser: 'Firefox', visitors: 187, fill: 'var(--chart-3)' },
];
<BarChart
data={data}
config={{ visitors: { label: 'Visitors' } }}
xKey="browser"
/>;Composing with the chart primitive
When you need full control, skip BarChart and compose raw recharts inside ChartContainer. The container still injects your token colors and renders the tooltip styling, so you only write the recharts you actually need.
import {
ChartContainer,
ChartTooltip,
ChartTooltipContent,
} from '@gremorie/rx-data';
import { Bar, BarChart, CartesianGrid, XAxis } from 'recharts';
<ChartContainer config={config}>
<BarChart accessibilityLayer data={data}>
<CartesianGrid vertical={false} />
<XAxis dataKey="month" tickLine={false} axisLine={false} tickMargin={10} />
<ChartTooltip cursor={false} content={<ChartTooltipContent />} />
<Bar dataKey="desktop" fill="var(--color-desktop)" radius={8} />
<Bar dataKey="mobile" fill="var(--color-mobile)" radius={8} />
</BarChart>
</ChartContainer>;Compose raw recharts when the surface needs extra reference lines, a custom legend, or mixed series. ChartContainer owns the responsive frame and the token color vars.
Accessibility
- Accessibility layer: recharts'
accessibilityLayeris enabled, providing keyboard navigation and screen-reader announcements for the data points. - Token contrast:
--chart-1through--chart-5ship with WCAG AA contrast against the card background in both light and dark themes. - Container element: the wrapper renders a
ChartContainerdiv with the series colors applied as CSS variables. - No streaming UI: charts do not implement a streaming append affordance. For live counts, throttle parent updates.
Related
- LineChart - ordered domain when shape matters more than discrete comparison.
- AreaChart - filled magnitude over an ordered domain.
- ScatterChart - independent X plus Y when both axes are numeric.