# Donut chart (goodtabs UI)

A donut chart in plain SVG with the total in the middle and a legend with the numbers.

## Install

```bash
npx shadcn@latest add https://ui.goodtabs.co/r/donut-chart.json
```

Or, with the @goodtabs namespace configured in components.json: `npx shadcn@latest add @goodtabs/donut-chart`

## Usage

```tsx
import { DonutChart } from "@/components/ui/donut-chart"

<DonutChart title="Visits by source" data={[{ label: "Direct", value: 54 }, { label: "Search", value: 38 }]} />
```

## Props

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| data | `{ label: string; value: number }[]` |  | The parts of the whole. Up to five read well. |
| title | `string` |  | What the chart shows, for screen readers. |
| totalLabel | `string` | `"Total"` | Small label under the total. |
| highlight | `number` |  | Index of the one slice drawn in the brand colour. |
| format | `(value: number) => string` | `String` | Formats the total and the legend values. |

## When to use

- Showing how a total splits into two to five parts
- A dashboard card where the total matters as much as the split
- With a highlight when one share is the point

## When not to use

- More than five or six parts, where a sorted list or bars read better
- Comparing values across time: use the area chart
- Parts that do not add up to a meaningful whole

## Notes for agents

- Server component, no dependencies. Needs a width; the ring caps at 160px and centres
- Tone follows size rank, strongest foreground for the largest slice. Only the highlight uses brand
- The legend is the text alternative: label, value and percentage per slice, and the ring is aria-hidden
- Pass values, not percentages. Zero-value slices draw nothing but still list in the legend

## The maths

- Each arc is value / total × C where C = 2πr and r = 40, so C ≈ 251.3 and the slices always close the ring.
- A 1.5 unit gap is cut from the end of each dash, which keeps slices apart without trimming the first or last.
- The ring is rotated -90 degrees so the first slice starts at 12 o'clock, since a circle's stroke begins at 3.

Docs: https://ui.goodtabs.co/components/donut-chart