Charts
Recharts and Chart.js are the two React charting libraries most projects
actually reach for, and they take opposite approaches: Recharts composes SVG out
of React elements, Chart.js paints a canvas from a config object. Both are shown
here, and both are made to look like the rest of the app the same way — by
reading the design tokens out of CSS and handing them over as plain values.
Recharts
Both examples read their colours from one small
useChartTokens hook — the
whole of it is in the theme bridge below the install
commands.Area chart in a Card
Recharts draws the plot; the card, the title, the badge and the tooltip surface are all Algorize UI. The chart library never renders anything the design system already owns.
- Pass
stroke - and
fillthe resolved token values —tokens.borderfor the grid,tokens.mutedfor axis ticks. contentStyle- is how the built-in
Tooltipis repainted; it takes inline style, sotokens.cardandtokens.bordergo straight in. ResponsiveContainer- needs a parent with a real height —
h-[280px]here. A percentage height inside an auto-height parent collapses to zero.
Installation
This example also uses these Algorize UI components — install whichever
your project does not already have:
The theme bridge
A chart cannot read
text-muted-foreground. Recharts needs a stroke string,
Chart.js needs a borderColor for a canvas, and AG Grid — on the
Data Tables page — needs the same
values again. So the token lookup lives in one small hook rather than in each
chart:Two details earn their place. Colours are read off
document.documentElement,
so anything defined in globals.css is available without a provider. And the
MutationObserver on the root element's class is what makes a chart follow a
theme switch — next-themes toggles that class, and a canvas painted before the
toggle will not repaint on its own.The series palette is literal hex rather than a token, deliberately: the default
--primary is a greyscale ramp, so a six-series chart drawn from it would be six
indistinguishable greys. Swap those six hues for your brand ramp and every chart
on this page follows.Chart.js
Bar and doughnut
Chart.js is tree-shaken, so every scale, element and plugin has to be registered once. Do it at module scope — a ChartJS.register call in a render body runs on every update.
- Wrap
options - in
useMemokeyed on the tokens. Rebuilding the options object is what makes a canvas chart follow the theme switch; it cannot inherit anything from CSS. maintainAspectRatio{false}- lets the chart fill its container instead of forcing a 2:1 box. Pair it with a fixed-height wrapper.
borderColor- on the doughnut is set to
tokens.card, so the gap between arcs is the card surface rather than white in dark mode.
Installation
This example also uses these Algorize UI components — install whichever
your project does not already have:
Which one
| Recharts | Chart.js | |
|---|---|---|
| Renders | SVG elements | Canvas |
| Composition | React children (<Area>, <XAxis>) | One config object |
| Custom marks | Any React component | Plugin API |
| Many points | Slows down — every point is a DOM node | Stays fast |
| Theme change | Re-renders like any React tree | Needs the options object rebuilt |
Reach for Recharts when the chart is part of the component tree and you want to
drop your own React nodes into it. Reach for Chart.js when the series are long
enough that a few thousand SVG nodes would hurt.
Neither example hard-codes a colour at the call site — both index
tokens.series. Changing the palette in chart-tokens.ts restyles every chart
in the app at once, which is the point of routing colour through the bridge
rather than passing hex into each component.