Table of contents
DonutChart
Parts of a whole, when the whole is worth naming and the parts are few.
The ring sweeps in clockwise from twelve o'clock, one segment after the next, and the middle of the ring carries the total — the number a reader wants before they want any share of it. Hover or arrow onto a segment and it lifts out of the ring while the centre switches to that part's value and share. A 2px gap in the card colour keeps neighbouring segments apart without an outline. Past five parts the palette stops rather than inventing hues: group the tail into an "Other" datum yourself, which is also the honest chart. Every part is also a row in a visually-hidden table, inside a clipped box: a table grows to fit its content whatever width it is given, so on its own it would widen a phone page.
Charts · keyboard contract
<script lang="ts">
import { DonutChart } from '@l4st/driftwood';
</script>
| Light | Dark |
|---|---|
![]() |
![]() |
Props
| Prop | Type | Default | What it does |
|---|---|---|---|
data required |
ChartDatum[] |
— | The parts, largest first reads best. Values must be non-negative. |
size |
number |
180 |
Outer diameter of the ring, in pixels. |
thickness |
number |
22 |
Ring thickness. Under about a tenth of size it stops reading as a ring. |
centerLabel |
string |
'Total' |
Replaces the centre caption. Defaults to "Total". |
format |
(value: number) => string |
compact |
Formats every value: centre, tooltip, legend and table. |
legend |
boolean |
true |
Hide the legend. The table view still names every part. |
partsLabel |
string |
'Part' |
Heads the part column of the screen-reader table — what the parts are ('File type', 'Region'). |
aria-label required |
string |
— | Names the chart, and captions the table. Required. |
class |
string |
— | Merged with the component's own classes, last — so yours win. |
Keyboard
| Key | Does |
|---|---|
| ← / ↑, → / ↓ | move between segments — the ring wraps |
| Home / End | first / last segment |
| Escape | return the centre to the total |
Example
The markup behind the screenshot above, lifted from src/routes/shots/ — so it
compiles, and it is exactly what produced the image.
<DonutChart
data={[
{ label: 'Media', value: 5240 },
{ label: 'Backups', value: 3180 },
{ label: 'Code', value: 980 },
{ label: 'Archives', value: 620 }
]}
partsLabel="Category"
aria-label="Gigabytes stored, by category"
/>
Notes
ChartDatum
type ChartDatum = {
/** Names the part in the legend, the tooltip and the table view. */
label: string;
/** Its magnitude. Negative values are not meaningful in a part-of-whole chart. */
value: number;
/** Overrides the palette slot. */
color?: string;
};
Five parts, at most
The palette has five slots and stops there rather than generating a sixth hue, because the five are validated as an ordered set for colour blindness and a generated one is not. A donut of nine slices is also unreadable on its own terms: sort descending, keep the parts that matter, and sum the rest into an "Other" datum.
If the parts do not sum to a meaningful whole, this is the wrong chart — reach for BarChart.
Charts · LineChart · BarChart · ShareBar · Heatmap · Gauge · Sparkline · ChartLegend
driftwood
Layout
Actions
Forms
- Field
- Input
- FileInput
- FileList
- Textarea
- CodeEditor
- Combobox
- RadioGroup
- NumberInput
- InlineEdit
- Label
- Select
- MultiSelect
- DatePicker
- TagsInput
- Checkbox
- Switch
- Slider
Feedback
Charts
Overlays
Navigation
Generated from the source by pnpm wiki · repository · v0.24.0

