<!-- Protocore Design System — PieChart -->
# PieChart

- **Category:** Charts (`charts`)
- **Slug:** `charts/pie-chart`
- **Status:** stable
- **Platforms:** web
- **Import:** `import { PieChart, DonutChart } from "@protocore/pds/charts";`
- **Docs:** https://pds.protocore.io/components/charts/pie-chart

> A monochrome-plus-signal pie chart with sharp sectors and a custom legend; DonutChart is the same wrapper with a ring cutout.

## Import path

`PieChart` and `DonutChart` ship from the **`@protocore/pds/charts`** subpath so recharts stays out of the core bundle. `recharts` (>=3) is an **optional peer**; install it in apps that render charts.

```tsx
import { PieChart, DonutChart } from "@protocore/pds/charts";
import { ChartContainer } from "@protocore/pds";
```

## When to use it

Use a **PieChart** or **DonutChart** to show a handful of parts making up a whole where the categories are few (three to five) and the shares are visibly different — status-class mix, plan distribution, spend by category. Beyond five slices, or when precise comparison matters, a [PercentageBarChart](/charts/percentage-bar-chart) or [BarChart](/charts/bar-chart) reads more honestly.

Spend a signal hue on at most one slice; let the rest stay monochrome (see the doctrine on [ChartContainer](/charts/chart-container)).

## Props

### DonutChart

| Prop | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `data` | `ReadonlyArray<Record<string, string \| number \| null \| undefined>>` | yes | — | One datum per slice; each keyed by `nameKey` (label) and `dataKey` (value). |
| `dataKey` | `string` | no | `"value"` | Datum key for each slice's numeric value. |
| `nameKey` | `string` | no | `"name"` | Datum key for each slice's label. |
| `colors` | `string[]` | no | — | Per-slice colour overrides, in data order. Defaults to the `--pds-chart-N` ramp. |
| `innerRadius` | `number \| string` | no | `0 (PieChart) · "58%" (DonutChart)` | Inner radius (donut hole) — px or a percentage string. |
| `outerRadius` | `number \| string` | no | `"80%"` | Outer radius — px or a percentage string. |
| `legend` | `boolean` | no | `true` | Render the custom swatch/label legend below the plot. |
| `height` | `number` | no | `240` | Chart height in px (plot + legend). |
| `...rest` | `Omit<RechartsPieChartProps, 'data' \| 'children' \| 'width' \| 'height' \| 'ref'>` | no | — | Remaining props spread onto the underlying recharts `<PieChart>`. |

### PieChart

| Prop | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `data` | `ReadonlyArray<Record<string, string \| number \| null \| undefined>>` | yes | — | One datum per slice; each keyed by `nameKey` (label) and `dataKey` (value). |
| `dataKey` | `string` | no | `"value"` | Datum key for each slice's numeric value. |
| `nameKey` | `string` | no | `"name"` | Datum key for each slice's label. |
| `colors` | `string[]` | no | — | Per-slice colour overrides, in data order. Defaults to the `--pds-chart-N` ramp. |
| `innerRadius` | `number \| string` | no | `0 (PieChart) · "58%" (DonutChart)` | Inner radius (donut hole) — px or a percentage string. |
| `outerRadius` | `number \| string` | no | `"80%"` | Outer radius — px or a percentage string. |
| `legend` | `boolean` | no | `true` | Render the custom swatch/label legend below the plot. |
| `height` | `number` | no | `240` | Chart height in px (plot + legend). |
| `...rest` | `Omit<RechartsPieChartProps, 'data' \| 'children' \| 'width' \| 'height' \| 'ref'>` | no | — | Remaining props spread onto the underlying recharts `<PieChart>`. |

## Examples

### Pie

Pass `data` and (optionally) `dataKey`/`nameKey`. Sectors are sharp (corner radius 0, matching the system's control geometry), hairline-separated in the surface colour, and coloured from the `--pds-chart-N` ramp — grey by default, with a signal hue reserved for the slice that carries meaning. The custom legend renders beneath the plot.

```tsx
import { ChartContainer } from "@protocore/pds";
import { PieChart } from "@protocore/pds/charts";

const data = [
  { name: "2xx", value: 82 },
  { name: "4xx", value: 12 },
  { name: "5xx", value: 6 },
];

export default function PieChartBasics() {
  return (
    <ChartContainer label="Requests by status class · 24h" height={280}>
      <PieChart data={data} />
    </ChartContainer>
  );
}
```

### Donut

`DonutChart` is the same wrapper with a non-zero `innerRadius` — a ring. Use the negative space in the middle for a headline number (a [RadialProgress](/charts/radial-progress) or a plain figure) so the part-to-whole reading and the total sit together.

```tsx
import { ChartContainer } from "@protocore/pds";
import { DonutChart } from "@protocore/pds/charts";

const data = [
  { name: "Hobby", value: 1840 },
  { name: "Pro", value: 920 },
  { name: "Enterprise", value: 240 },
];

export default function DonutChartDemo() {
  return (
    <ChartContainer label="Active tenants by plan" height={280}>
      <DonutChart data={data} />
    </ChartContainer>
  );
}
```

## Do & don't

**Do**

- Keep it to three to five slices with clearly different shares.
- Let slices stay grey and spend a signal hue on the one that matters.
- Use DonutChart when you want a headline total in the middle.
- Wrap it in a ChartContainer so it inherits the `--pds-chart-*` ramp.

**Don't**

- Don't use a pie for many near-equal slices — that's a bar or percentage bar.
- Don't round the sectors or add shadows; sharp geometry is the house style.
- Don't import it from `@protocore/pds`; it lives on the `/charts` subpath.
- Don't rely on colour alone — the legend labels every slice.

## Accessibility

**Notes**

- recharts renders the plot as SVG; provide surrounding context (a ChartContainer `label`, caption, or data table) since individual sectors are not labelled.
- The custom legend labels every slice, so the chart stays readable in grayscale and for colour-vision deficiencies.
- The default tooltip surfaces per-slice values on hover and keyboard focus via recharts.

## Related

`percentage-bar-chart`, `bar-chart`, `chart-container`, `chart-legend`

---

© Protocore. All rights reserved. Use of the Protocore Design System requires prior written authorization from Protocore (contact@protocore.io). These machine-readable materials must not be ingested into ML-training datasets or derivative design systems. See https://pds.protocore.io/legal/
