Components
Chart
View in FigmaA responsive, token-themed wrapper around any Recharts chart. ChartContainer provides labels + colours from a ChartConfig and injects the --color-<key> variables; the tooltip and legend read the same config.
Install
npx shadcn@latest add @alix/chartPreview
Usage
const config = {
revenue: { label: "Net revenue", color: "var(--chart-1)" },
} satisfies ChartConfig;
<ChartContainer config={config} className="aspect-auto h-72">
<AreaChart data={data}>
<CartesianGrid vertical={false} />
<XAxis dataKey="month" tickLine={false} axisLine={false} />
<ChartTooltip content={<ChartTooltipContent />} />
<Area dataKey="revenue" stroke="var(--color-revenue)" fill="var(--color-revenue)" />
</AreaChart>
</ChartContainer>Examples
01
Two series with a legend
Use the shared config to keep series labels, colours, tooltip rows, and legend swatches in sync.
const chartSeriesData = [
{ month: "Jan", revenue: 18.4, target: 17.8 },
{ month: "Feb", revenue: 19.7, target: 18.8 },
{ month: "Mar", revenue: 20.3, target: 20.1 },
{ month: "Apr", revenue: 21.6, target: 21.0 },
{ month: "May", revenue: 22.4, target: 22.2 },
{ month: "Jun", revenue: 23.6, target: 23.1 },
];
const chartSeriesConfig = {
revenue: { label: "Revenue", color: "var(--chart-1)" },
target: { label: "Target", color: "var(--chart-5)" },
} satisfies ChartConfig;
<ChartContainer config={chartSeriesConfig} className="aspect-auto h-64 w-full">
<LineChart data={chartSeriesData} margin={{ left: 4, right: 12, top: 8, bottom: 0 }}>
<CartesianGrid vertical={false} />
<XAxis dataKey="month" tickLine={false} axisLine={false} tickMargin={8} />
<YAxis tickLine={false} axisLine={false} tickMargin={8} width={32} />
<ChartTooltip content={<ChartTooltipContent indicator="line" />} />
<ChartLegend content={<ChartLegendContent />} />
<Line dataKey="revenue" type="monotone" stroke="var(--color-revenue)" strokeWidth={2} dot={false} />
<Line dataKey="target" type="monotone" stroke="var(--color-target)" strokeWidth={2} strokeDasharray="4 4" dot={false} />
</LineChart>
</ChartContainer>02
Grouped bar comparison
Bar charts work when leaders need to compare planned and delivered capacity across practices.
const chartBarData = [
{ practice: "TRS", planned: 42, delivered: 38 },
{ practice: "PI", planned: 36, delivered: 34 },
{ practice: "TIS", planned: 30, delivered: 32 },
{ practice: "ID", planned: 24, delivered: 21 },
];
const chartBarConfig = {
planned: { label: "Planned", color: "var(--chart-5)" },
delivered: { label: "Delivered", color: "var(--chart-1)" },
} satisfies ChartConfig;
<ChartContainer config={chartBarConfig} className="aspect-auto h-64 w-full">
<BarChart data={chartBarData} margin={{ left: 4, right: 12, top: 8, bottom: 0 }}>
<CartesianGrid vertical={false} />
<XAxis dataKey="practice" tickLine={false} axisLine={false} tickMargin={8} />
<YAxis tickLine={false} axisLine={false} tickMargin={8} width={32} />
<ChartTooltip content={<ChartTooltipContent />} />
<ChartLegend content={<ChartLegendContent />} />
<Bar dataKey="planned" fill="var(--color-planned)" radius={0} />
<Bar dataKey="delivered" fill="var(--color-delivered)" radius={0} />
</BarChart>
</ChartContainer>03
Inside a panel
Panel owns the dashboard frame while ChartContainer owns the responsive Recharts area.
Revenue bridge
Trailing six months, $M
On track
<Panel
title="Revenue bridge"
description="Trailing six months, $M"
actions={<Badge variant="success" dot>On track</Badge>}
>
<ChartContainer config={chartConfig} className="aspect-auto h-48 w-full">
<AreaChart data={chartData} margin={{ left: 4, right: 8, top: 8, bottom: 0 }}>
<defs>
<linearGradient id="docPanelFillRevenue" x1="0" y1="0" x2="0" y2="1">
<stop offset="0%" stopColor="var(--color-revenue)" stopOpacity={0.22} />
<stop offset="95%" stopColor="var(--color-revenue)" stopOpacity={0} />
</linearGradient>
</defs>
<CartesianGrid vertical={false} />
<XAxis dataKey="month" tickLine={false} axisLine={false} tickMargin={8} />
<ChartTooltip content={<ChartTooltipContent />} />
<Area dataKey="revenue" type="monotone" stroke="var(--color-revenue)" strokeWidth={2} fill="url(#docPanelFillRevenue)" />
</AreaChart>
</ChartContainer>
</Panel>When to use it
Use it for
- Executive dashboards where a metric needs axes, gridlines, tooltips, or a legend.
- Token-coloured Recharts series that must stay consistent across the chart, tooltip, and legend.
- Panel bodies that need a responsive chart without adding a second ResponsiveContainer.
Reach for something else
- Tiny trend marks inside KPI cards or table cells — use Sparkline instead.
- Tabular ledger data that users need to compare row by row — use DataTable instead.
- Single headline metrics without an axis or interaction need — use Stat or StatCard instead.
Props
| Prop | Type | Default | Description |
|---|---|---|---|
| config | ChartConfig | — | Maps each series key to { label, color }. The colour is injected as --color-<key> on the chart root, so series reference var(--color-<key>) and the tooltip/legend resolve labels and swatches automatically. |
| children | ReactElement | — | A single Recharts chart element (e.g. <AreaChart>). The ResponsiveContainer is supplied for you — don't add your own. |
| className | string | — | Defaults to a 16:9 box; override with a height (e.g. "aspect-auto h-72"). |
| ChartTooltip / ChartTooltipContent | components | — | Recharts <Tooltip> + a themed body. Use as <ChartTooltip content={<ChartTooltipContent />} />. |
| ChartLegend / ChartLegendContent | components | — | Recharts <Legend> + a themed body. Use as <ChartLegend content={<ChartLegendContent />} />. |