Donut chart
ProParts of a whole. Six parts at most; the rest fold into "Other" in neutral grey rather than a seventh hue. Segments are separated by a 2px gap; the total sits in the middle. The legend carries each part's value and share, so nothing depends on matching colours.
Preview
Install
With the Candor CLI
First time? Get started sets up the registry and theme. Or with shadcn directly: npx shadcn@latest add @candor/donut-chart
Brings in: chart-frame, data, locale, scale
Usage
"use client"
import { DonutChart, type DonutPart } from "@/components/donut-chart"
const changes: DonutPart[] = [
{ label: "API handlers", value: 14 },
{ label: "UI components", value: 22 },
{ label: "Migrations", value: 9 },
{ label: "Background jobs", value: 7 },
{ label: "Feature flags", value: 5 },
{ label: "Dashboards", value: 3 },
{ label: "Infrastructure config", value: 2 },
]
export default function Example() {
return <DonutChart className="max-w-xl" title="What’s changing" subtitle="Changes in the 4.2 release" parts={changes} totalLabel="changes" />
}<DonutChart>
| Prop | Type | Default | Description |
|---|---|---|---|
| titlerequired | string | — | What the chart shows, above it. |
| subtitle | string | undefined | — | A line under the title, e.g. the period or unit. |
| partsrequired | DonutPart[] | — | The parts of the whole; past six, the smallest fold into Other. |
| format | ValueFormat | undefined | "number" | How values are written: number, percent (0–1), currency (USD) or duration (seconds). Defaults to number. |
| totalLabel | string | undefined | — | The word under the total in the middle. Defaults to "Total". |
| state | ChartState | undefined | — | Loading, empty, partial or error. Parts that sum to zero show as empty. |
| className | string | undefined | — | Extra classes for the outer element. |
Strings
The fixed words, in English by default. Change any of them under donutChart in <LocaleProvider strings={{ … }}>; the table is exported as donutChartStrings.
| Key | English |
|---|---|
| total | Total |
| other | Other |
| empty | Nothing to divide up yet. |
| value | Value |
| share | Share |
| ofTotal | of total |
| part | {label} {value} |
Types
- DonutPart
{ label: string; value: number }