Charts
DrumKit ships no chart component — just what recharts asks for: legend, tooltip, active dot, and tick thinning. The plot itself is composed at the call site.
Charts
DrumKit ships no chart component — just what recharts asks for: legend, tooltip, active dot, and tick thinning. The plot itself is composed at the call site.
Demo
The five families, browsable the way the Figma sets present them: pick a chart, flip its variant axes, copy the recipe.
The variant axes are the sheet’s own
Contextual demo
A legend and a tooltip only make sense attached to a chart. The preview puts the family in an analytics panel.
The family
Four exports from one file: three recharts content components and a pure helper. There is deliberately no Chart wrapper.
| Component | Description | Import from |
|---|---|---|
| ChartLegendContent | The legend’s markup: a ul of rows, each an 8px swatch and a text-sm label. Passed to recharts’ Legend as content; horizontal and vertical layouts, three alignments, and an optional reversed order. | @/components/application/charts/charts-base |
| ChartTooltipContent | The hover bubble’s markup: a near-black card with a semibold title and either one supporting line or one row per series. Passed to recharts’ Tooltip as content. | @/components/application/charts/charts-base |
| ChartActiveDot | The marker recharts draws on the hovered point: a 12px ring in utility-brand-600 over a bg-primary core. Passed to a Line or Area as activeDot. | @/components/application/charts/charts-base |
| selectEvenlySpacedItems | A pure helper, not a component: picks a fixed number of evenly spaced items from an array, with the last item pinned. Used to thin a dense x-axis down to the ticks the sheet draws. | @/components/application/charts/charts-base |
The five families, composed
Every chart the sheet draws, built from recharts primitives with the kit’s content in their slots. Nothing new ships — these live in this page’s config.
Active users
8,270
Still no component
config.tsx, with the kit’s ChartLegendContent, ChartTooltipContent, and ChartActiveDot in their slots — which is the recipe the Code tab’s examples carry. The values they are built to — the ring diameters, the 50% hole, the 6px bar radius, the 20% radar fill, the 8%-to-0 wash — were read from the sheet’s exported art on 2026-08-27.Chart markers
The sheet’s three hover treatments on one series, each pinned open on Jan 10 the way the set draws them. Hover to move the marker — the cursor, the dot, and the bubble’s second line are what change.
Only the Line type ships
ChartActiveDot is the sheet’s Line marker — the ⌀12 ring over the white core. Dash and Minimal have no kit counterpart: the solid dot is a one-element component in this page’s config, and both cursors are recharts’ own cursor prop on the Tooltip — a 2px round-capped stroke-utility-brand-600 line, with strokeDasharray="0.1 6" supplying the Dash type’s dots. Read from the sheet’s exported cursor strokes.formatter and labelFormatter split the Minimal bubble
formatter keeps the value while labelFormatter is left formatting only the supporting line — and returning an empty string from it removes the date without touching the value. Passing only labelFormatter={() => ""} would blank the title too, because without a formatter the title falls through to labelFormatter. Read from the source’s ternary chain, and the reason the Minimal cell passes both.The tooltip
Two drawn layouts, chosen by how many entries the payload holds. Rendered on a mock payload with active set by hand.
Dec 2025
Desktop: 5,310
Mobile: 2,960
8,270
Dec 2025
2,960
Mobile web, unauthenticated sessions in the EU region
Two edits landed on the bubble on 2026-08-23
font-medium, matching the sheet’s xs Medium, and the text stack gained a 296px cap (max-w-74) it did not have at all — an unbounded bubble grew as wide as its longest line. The background, padding, radius, shadow, title tokens, and supporting tokens all matched the sheet already, down to the third shadow layer’s −1px spread.The bubble is pointer-and-arrow-key only
div with no role, no aria-live, and no accessible name. recharts’ own accessibility layer makes the chart focusable and moves the active point with the arrow keys, so a keyboard user can reach these values — but nothing announces them when they change. The Accessibility section on the Code tab says what you have to add.The active dot
The marker recharts draws on the hovered point. A 12px box with the ring inside it, decorative, and now aria-hidden.
The geometry changed on 2026-08-23
rx 6 and a centered 2px stroke — which draws an outer ⌀10 over a ⌀6 core — to 10×10 at x and y 1 with rx 5, so the same 2px stroke draws inside the 12px box and lands on the sheet’s ⌀12 ring over a ⌀8 core. The tokens were already right. The svg is also aria-hidden now, and it honors the className recharts types let you pass; it used to accept the prop and drop it.Tick sampling
selectEvenlySpacedItems thins a dense axis to a fixed count, walking a fixed stride with the last item pinned.
Jan · Mar · May · Jul · Sep · Nov · Dec
2 · 6 · 10 · 14 · 18 · 22 · 26 · 30
1 · 5 · 9 · 13 · 17 · 21 · 25 · 30
Mon · Tue · Wed · Thu · Fri · Sat · Sun
The stride rule, and what changed
span = length − 1, the helper walks a stride of ceil(span / (count − 1)) — clamped down to floor((span − 1) / (count − 2)) and floored at 1 — for the first count − 1 picks, then pins the array’s last item. Twelve months at seven ticks gives a stride of 2 and draws Jan, Mar, May, Jul, Sep, Nov, Dec — the sheet’s own row (1061:47553). The rounded interpolation it replaced put Aug and Oct in the fifth and sixth slots. The 7-day identity and the sheet’s fifteen-tick 30-day row are unchanged by the edit; thirty daily labels sampled to eight is a different array, and the clamp moved its middle picks from 18, 22, 26 to 17, 21, 25.Which 30-day array the sheet’s row comes from
selectEvenlySpacedItems(desktopTicks, 8) on those fifteen items, which is the second cell above, and it matches to the label. Thirty daily labels sampled to eight is a different question with a different answer (the third cell), so do not check the sheet’s row against it.Why the stride is clamped
ceil(span / (count − 1)) can walk the strided run all the way onto the final index, and the pin then repeats it — thirty labels at eight ticks did exactly that. Clamping the stride down to floor((span − 1) / (count − 2)) stops the run one index short, so the third cell above returns eight distinct days. Read from the source. One case is inherent rather than fixable: an array shorter than count has too few items to fill the request, so it repeats — four labels at eight ticks ends on five copies of the last one, four extra strided picks plus the pin. Guard short series before sampling.