/

React Chart Components: shadcn Charts and When to Reach for D3

Three kinds of chart with three different requirements, the accessibility fix nobody ships, and where the performance actually goes.

Serafim Korablev
Serafim Korablev
@korablev

Most charts in product interfaces are not analysis, they are a number with a shape behind it. That distinction decides everything downstream: how much library you need, how much of the chart has to be interactive, and whether the thing you are building should be a chart at all rather than a large number and a percentage.

210 public components on 21st carry the chart tag. Sorted by what the reader is being asked to do, there are three groups, and only one of them needs a real charting library.

The stat with a shape

A headline figure, a change against the previous period, and a small line behind it for context. Progress Metric Card by Mak VieSAinte is the reference: a KPI card pairing a large figure with a Recharts series that switches between a curve and bars. Mini Chart by Jatin Yadav and Animated Card Chart by badtz are the compact versions, and Stats Widget by Ravi Katiyar is the financial-figure variant.

For this group the sparkline is decoration with a job: it tells the reader whether the number has been going up. It needs no axes, no tooltip, no legend, and it should never be the only place the trend is stated - put the change in text beside it.

The dashboard chart

A real series that someone reads. Area Chart and Funnel Chart by bklitai, Donut Chart by Ravi Katiyar, Line Charts 9 by sean0205 and Radar Chart by LegionWebDev cover the common shapes. Real time Analytics by Kousthubha Yadiyala is the live-updating panel.

Three decisions matter more than the library here. Pick the chart from the question: change over time is a line, composition is a stacked bar rather than a pie, comparison between categories is a bar, and correlation is a scatter. Never start a bar chart's axis anywhere but zero, because the bar's length is the encoding. And a pie with more than about five slices is a table.

The one that should not be a chart

If the reader's question is "what is the number", give them the number. A gauge showing 43% is a worse presentation of 43% than the characters 43%. Charts earn their place when the shape carries information the number cannot: a trend, a distribution, an outlier.

The accessibility problem nobody solves

An SVG chart carries no values for anyone using a screen reader. An aria-label on the container announces the title and nothing else, which is the equivalent of a caption with the data removed.

The fix is unglamorous and complete: render the same rows as a real HTML table, either visually hidden or behind a "view as table" toggle. It costs a few lines, it makes the numbers selectable and copyable, and it is the only approach that works with every assistive technology rather than the ones that happen to support a given ARIA pattern.

Two more, cheap and usually missing. Never encode a series by colour alone - add a shape, a dash pattern or a direct label, so the chart survives colour blindness and a black-and-white print. And check the palette against the background at the sizes you actually draw: a 1px line at 40% opacity is not a passing contrast ratio.

Where the performance goes

Charts are cheap until one of three things happens.

Too many points. An SVG path with ten thousand nodes is ten thousand DOM elements' worth of parsing even as one element. Downsample before rendering: for a line chart, a largest-triangle-three-buckets pass keeps the visual shape at a fraction of the points.

Animation on every update. A live chart that re-runs its entrance animation on each poll spends the whole frame budget on transitions nobody asked for. Animate on mount, then update in place.

Recharts is bigger than the chart. For a sparkline in a card, a hand-written SVG path is a few lines of code and no dependency. Reach for a library at the point where you need axes, ticks, tooltips and responsiveness, which is exactly where writing it yourself stops being cheap.

Where else to look

The honest list of alternatives, because the answer is not always us:

SourceBest forTrade-off
shadcn/ui ChartsRecharts wired to your theme tokens, with a decent tooltipRecharts' size and its update behaviour come with it
RechartsThe common shapes with the least ceremonyLarge bundle, and awkward past a few thousand points
visx / D3Full control, unusual chart types, custom interactionYou are building the chart, not configuring one
A hand-written SVG pathSparklines and single-series shapesNothing else: no axes, no tooltip
21stFinished KPI cards, funnels, radars and live panelsQuality varies by author, so preview before you take it

Taking one

Every component page has a live preview and the code. Installing goes through the shadcn CLI against our registry:

bash

That key comes from your 21st account, and installs require a membership. Set API_KEY_21ST once in your shell and the command works for anything in the catalogue. The 21st MCP covers the same ground without leaving the editor: ask Claude, Cursor or Codex for a chart, get the previews inline, and let the agent write the file.

Browse chart components →

Frequently asked

Which chart library should I use with shadcn/ui?
shadcn/ui's own Charts wrap Recharts and wire it to your theme tokens, which covers the common shapes with the least work. Reach past it when you need unusual chart types, custom interaction or tens of thousands of points, where visx or D3 give you control that configuration cannot. For a sparkline inside a card, a hand-written SVG path beats every library.
How do you make a chart accessible?
Render the same data as a real HTML table, either visually hidden or behind a view-as-table toggle. An SVG chart carries no values, and an aria-label announces only the title. Also never encode a series by colour alone: add a shape, a dash pattern or a direct label so the chart survives colour blindness and greyscale printing.
Why is my chart slow?
Usually too many points or animation on every update. Downsample before rendering, with something like largest-triangle-three-buckets for a line, which keeps the visual shape at a fraction of the nodes. And animate on mount only: a live chart that re-runs its entrance transition on each poll spends the whole frame budget on it.
When is a chart the wrong choice?
When the reader's question is what the number is. A gauge showing 43% is a worse presentation of 43% than the characters themselves. Charts earn their place when the shape carries something the number cannot: a trend, a distribution or an outlier.

Published

Aug 20, 2026

Read time

6 min

Tags

GuideChartsReactDashboards

Share