Donut Chart
Shows how parts make up a whole as a ring.
Installation
pnpm dlx shadcn@latest add @paneui/donut-chartUsage
Examples
Keyboard
Each segment is a tab stop. Arrow keys cycle between segments, Esc blurs. The centre readout and legend follow the focused segment, and a hidden table mirrors the data for screen readers.
Motion
With reduced motion, segments appear at once instead of drawing in.
DonutChart
Also accepts every prop of div.
- segments*
- { id: string; label: string; value: number; color?: string; description?: string }[]
- Slices in order. Non-positive values are skipped.
descriptionshows under the label in the legend and is read with the segment. - label= "Donut chart"
- string
- Accessible name of the chart.
- thickness= 22
- number
- Ring thickness in viewBox units (the box is 200×200).
- gap= 4
- number
- Gap between segments in viewBox units. Ends are rounded when every segment is long enough for round caps; otherwise all ends are square, so small segments never overlap their neighbours.
- formatValue= formatNumber
- (value: number) => string
- Formats values in the centre, legend and tooltip.
- totalLabel= the locale's
- string
- Centre caption when nothing is hovered.
- maxSize= 240
- number
- Max ring diameter in px; it shrinks with its container.
- showLegend= true
- boolean
- Show the value / share legend.
- legendPosition= "side"
- "side" | "bottom"
sidesits beside the ring from thesmbreakpoint.- activeId
- string | null
- Controlled highlighted segment.
- defaultActiveId
- string | null
- Initially highlighted segment.
- onActiveChange
- (id: string | null) => void
- Called on hover, focus and leave.
| Prop | Type | Default | Description |
|---|---|---|---|
| segments* | { id: string; label: string; value: number; color?: string; description?: string }[] | — | Slices in order. Non-positive values are skipped. description shows under the label in the legend and is read with the segment. |
| label | string | "Donut chart" | Accessible name of the chart. |
| thickness | number | 22 | Ring thickness in viewBox units (the box is 200×200). |
| gap | number | 4 | Gap between segments in viewBox units. Ends are rounded when every segment is long enough for round caps; otherwise all ends are square, so small segments never overlap their neighbours. |
| formatValue | (value: number) => string | formatNumber | Formats values in the centre, legend and tooltip. |
| totalLabel | string | the locale's | Centre caption when nothing is hovered. |
| maxSize | number | 240 | Max ring diameter in px; it shrinks with its container. |
| showLegend | boolean | true | Show the value / share legend. |
| legendPosition | "side" | "bottom" | "side" | side sits beside the ring from the sm breakpoint. |
| activeId | string | null | — | Controlled highlighted segment. |
| defaultActiveId | string | null | — | Initially highlighted segment. |
| onActiveChange | (id: string | null) => void | — | Called on hover, focus and leave. |