PieChart
Pie and donut charts with labels, a center value, an active slice and stacked rings.
Simple
One slice per row; each row's fill picks its color.
January - June 2024
| Browser | Visitors |
|---|---|
| Chrome | 275 |
| Safari | 200 |
| Firefox | 187 |
| Edge | 173 |
| Other | 90 |
Code
<!-- each row's fill colors its slice: fill: "var(--color-chrome)" -->
<PieChart data={browsers} config={browserConfig} value="visitors" name="browser"
class="chart-demo-pie" tooltip={{ hideLabel: true }} />Usage
import { PieChart } from "@elements/ui/chart-pie";
import type { ChartConfig } from "@elements/ui/chart";
const config: ChartConfig = {
chrome: { label: "Chrome", color: "var(--chart-1)" },
safari: { label: "Safari", color: "var(--chart-2)" },
};
<PieChart data={rows} {config} value="visitors" name="browser" />
<PieChart data={rows} {config} value="visitors" name="browser"
innerRadius={60} centerValue="1,125" centerLabel="Visitors" />Examples
Separator none
separator=0 removes the gap between slices.
January - June 2024
| Browser | Visitors |
|---|---|
| Chrome | 275 |
| Safari | 200 |
| Firefox | 187 |
| Edge | 173 |
| Other | 90 |
Code
<PieChart data={browsers} config={browserConfig} value="visitors" name="browser"
separator={0} tooltip={{ hideLabel: true }} />Label
labels puts each value outside its slice on a leader line.
January - June 2024
| Browser | Visitors |
|---|---|
| Chrome | 275 |
| Safari | 200 |
| Firefox | 187 |
| Edge | 173 |
| Other | 90 |
Code
<PieChart data={browsers} config={browserConfig} value="visitors" name="browser"
labels tooltip={{ hideLabel: true }} />Custom label
Outside labels with no leader line; the tooltip names the value.
January - June 2024
| Browser | Visitors |
|---|---|
| Chrome | 275 |
| Safari | 200 |
| Firefox | 187 |
| Edge | 173 |
| Other | 90 |
Code
<PieChart data={browsers} config={browserConfig} value="visitors" name="browser"
labels={{ line: false }} tooltip={{ nameKey: "visitors", hideLabel: true }} />Label list
The browser name inside each slice, from the config.
January - June 2024
| Browser | Visitors |
|---|---|
| Chrome | 275 |
| Safari | 200 |
| Firefox | 187 |
| Edge | 173 |
| Other | 90 |
Code
<PieChart data={browsers} config={browserConfig} value="visitors" name="browser"
labels={{ position: "inside", key: "browser" }}
tooltip={{ nameKey: "visitors", hideLabel: true }} />Legend
A legend of the slices, named through the config.
January - June 2024
- Chrome
- Safari
- Firefox
- Edge
- Other
| Browser | Visitors |
|---|---|
| Chrome | 275 |
| Safari | 200 |
| Firefox | 187 |
| Edge | 173 |
| Other | 90 |
Code
<PieChart data={browsers} config={browserConfig} value="visitors" name="browser"
legend tooltip={false} />Donut
innerRadius makes a donut.
January - June 2024
| Browser | Visitors |
|---|---|
| Chrome | 275 |
| Safari | 200 |
| Firefox | 187 |
| Edge | 173 |
| Other | 90 |
Code
<PieChart data={browsers} config={browserConfig} value="visitors" name="browser"
innerRadius={60} tooltip={{ hideLabel: true }} />Donut active
active marks a slice and activeShape=grow pushes it out; hover moves it.
January - June 2024
| Browser | Visitors |
|---|---|
| Chrome | 275 |
| Safari | 200 |
| Firefox | 187 |
| Edge | 173 |
| Other | 90 |
Code
<PieChart data={browsers} config={browserConfig} value="visitors" name="browser"
innerRadius={60} separator={5} active={0} activeShape="grow"
tooltip={{ hideLabel: true }} />Donut with text
centerValue and centerLabel write in the hole.
January - June 2024
| Browser | Visitors |
|---|---|
| Chrome | 275 |
| Safari | 200 |
| Firefox | 187 |
| Edge | 173 |
| Other | 90 |
Code
<PieChart data={browsers} config={browserConfig} value="visitors" name="browser"
innerRadius={60} separator={5}
centerValue={total.toLocaleString()} centerLabel="Visitors"
tooltip={{ hideLabel: true }} />Stacked
Two value keys draw two rings; the tooltip heads each with its ring.
January - June 2024
| Month | Desktop | Mobile |
|---|---|---|
| January | 186 | 80 |
| February | 305 | 200 |
| March | 237 | 120 |
| April | 173 | 190 |
| May | 209 | 130 |
Code
<!-- two value keys from the same rows: two rings, the first inside -->
<PieChart data={months} config={config} value={["desktop", "mobile"]} name="month"
innerRadius={0} tooltip={{ nameKey: "month", indicator: "line" }} />Interactive
A month picker sets the active slice; activeShape=ring circles it and the center shows its value.
January - June 2024
| Month | Desktop |
|---|---|
| January | 186 |
| February | 305 |
| March | 237 |
| April | 173 |
| May | 209 |
Code
<select value={state.month}>...</select>
<PieChart data={months} {config} value="desktop" name="month"
innerRadius={60} separator={5} active={Number(state.month)} activeShape="ring"
centerValue={months[state.month].desktop.toLocaleString()} centerLabel="Visitors"
tooltip={{ hideLabel: true }} />Padding, corners and half pies
paddingAngle spaces the slices, cornerRadius rounds them, startAngle and endAngle draw part of a circle.
| Browser | Visitors |
|---|---|
| Chrome | 275 |
| Safari | 200 |
| Firefox | 187 |
| Edge | 173 |
| Other | 90 |
| Browser | Visitors |
|---|---|
| Chrome | 275 |
| Safari | 200 |
| Firefox | 187 |
| Edge | 173 |
| Other | 90 |
Code
<PieChart data={browsers} config={browserConfig} value="visitors" name="browser"
innerRadius="55%" paddingAngle={3} cornerRadius={6} separator={0} />
<PieChart data={browsers} config={browserConfig} value="visitors" name="browser"
startAngle={180} endAngle={0} innerRadius="60%" outerRadius="95%" />Legend toggles
A legend that hides and shows slices; the rest fill the circle.
| Browser | Visitors |
|---|---|
| Chrome | 275 |
| Safari | 200 |
| Firefox | 187 |
| Edge | 173 |
| Other | 90 |
Code
<PieChart data={browsers} config={browserConfig} value="visitors" name="browser"
innerRadius={50} legend={{ toggle: true }} hidden={state.hidden} />Controlled and keyboard
Tab to the chart; arrows move through the slices, Home and End jump, Escape hides the tooltip.
| Browser | Visitors |
|---|---|
| Chrome | 275 |
| Safari | 200 |
| Firefox | 187 |
| Edge | 173 |
| Other | 90 |
Code
<PieChart data={browsers} config={browserConfig} value="visitors" name="browser"
active={state.active} activeShape="grow" onActiveChange={() => state.changes++}
onItemClick={(i) => state.clicked = i} />Inactive slices
inactiveShape dim fades the slices that are not active while one is; the active one grows.
| Browser | Visitors |
|---|---|
| Chrome | 275 |
| Safari | 200 |
| Firefox | 187 |
| Edge | 173 |
| Other | 90 |
Code
<!-- while a slice is active, the others fade back -->
<PieChart data={rows} {config} value="visitors" name="browser" activeShape="grow" inactiveShape="dim" />Center and margin
margin insets the plot, then cx and cy place the center as px or a percentage of what is left; the radius is half the inset box's shorter side.
| Browser | Visitors |
|---|---|
| Chrome | 275 |
| Safari | 200 |
| Firefox | 187 |
| Edge | 173 |
| Other | 90 |
Code
<PieChart data={rows} {config} value="visitors" name="browser"
margin={{ left: 40 }} cx="40%" cy="60%" />Animation timing
animation sets when the marks start moving, how long they take and their easing: a CSS easing name, a cubic-bezier, spring, or a function of progress.
| Browser | Visitors |
|---|---|
| Chrome | 275 |
| Safari | 200 |
| Firefox | 187 |
| Edge | 173 |
| Other | 90 |
Code
<!-- wait 150ms, then take 900ms to enter or move to new data -->
<PieChart data={rows} {config} value="visitors" name="browser"
animation={{ begin: 150, duration: 900, easing: (t) => t * t }} />Legend and tooltip types
legendType on a config entry sets that item's legend icon, and none leaves it out of the legend; tooltipType none shows no tooltip for it. On the value key they apply to every item.
- Chrome
- Safari
- Firefox
- Edge
| Browser | Visitors |
|---|---|
| Chrome | 275 |
| Safari | 200 |
| Firefox | 187 |
| Edge | 173 |
| Other | 90 |
Code
<!-- safari's legend icon is a circle; firefox has no tooltip; other has no legend item -->
<PieChart data={rows} value="visitors" name="browser" legend config={{
...config,
safari: { label: "Safari", color: "var(--chart-2)", legendType: "circle" },
firefox: { label: "Firefox", color: "var(--chart-3)", tooltipType: "none" },
other: { label: "Other", color: "var(--chart-5)", legendType: "none" },
}} />Legend beside the pie
A vertical legend aligned right, centered on the pie.
- Chrome
- Safari
- Firefox
- Edge
- Other
| Browser | Visitors |
|---|---|
| Chrome | 275 |
| Safari | 200 |
| Firefox | 187 |
| Edge | 173 |
| Other | 90 |
Code
<!-- one item per line, beside the pie and centered on it -->
<PieChart data={browsers} {config} value="visitors" name="browser"
legend={{ layout: "vertical", align: "right", verticalAlign: "middle", iconType: "circle" }} />Minimum angle
A tiny value still gets a slice wide enough to see and point at.
| Browser | Visitors |
|---|---|
| Chrome | 275 |
| Safari | 200 |
| Firefox | 187 |
| Edge | 3 |
| Other | 90 |
Code
<!-- every slice with a value is at least 15 degrees wide -->
<PieChart data={rows} {config} value="visitors" name="browser" minAngle={15} />Zero and empty
A row with no value draws no slice and the keys pass over it; an empty data list draws an empty plot.
| Browser | Visitors |
|---|---|
| Chrome | 275 |
| Safari | 0 |
| Firefox | 187 |
| Edge | 173 |
| Other | 90 |
| Browser | Visitors |
|---|
Code
<!-- safari has 0 visitors: no slice, and the arrows skip it -->
<PieChart data={rows} {config} value="visitors" name="browser" />
<PieChart data={[]} {config} value="visitors" name="browser" />Radius cap
maxRadius keeps the pie at most 60px across its radius however large the chart grows.
| Browser | Visitors |
|---|---|
| Chrome | 275 |
| Safari | 200 |
| Firefox | 187 |
| Edge | 173 |
| Other | 90 |
Code
<PieChart data={browsers} config={browserConfig} value="visitors" name="browser" maxRadius={60} />Hidden rings and layout
hide leaves rings out while the rest keep their places; layout radial draws the same pie.
| Month | Desktop | Mobile |
|---|---|---|
| January | 186 | 80 |
| February | 305 | 200 |
| March | 237 | 120 |
| April | 173 | 190 |
| May | 209 | 130 |
| Month | Desktop | Mobile |
|---|---|---|
| January | 186 | 80 |
| February | 305 | 200 |
| March | 237 | 120 |
| April | 173 | 190 |
| May | 209 | 130 |
| Browser | Visitors |
|---|---|
| Chrome | 275 |
| Safari | 200 |
| Firefox | 187 |
| Edge | 173 |
| Other | 90 |
| Browser | Visitors |
|---|---|
| Chrome | 275 |
| Safari | 200 |
| Firefox | 187 |
| Edge | 173 |
| Other | 90 |
Code
<!-- the desktop ring is not drawn; mobile keeps its place outside it -->
<PieChart data={rows} {config} value={["desktop", "mobile"]} name="month" hide={["desktop"]} />
<!-- layout "radial" draws the same pie: a pie places its slices by its own angles and radii -->
<PieChart data={rows} {config} value="visitors" name="browser" layout="radial" />Moving to new data
animation matchBy pairs old and new slices by a key, so each browser keeps its color and turns to its new place; interpolate draws every frame with a function of your own, here one that sweeps each from its start angle.
| Browser | Visitors |
|---|---|
| Chrome | 275 |
| Safari | 200 |
| Firefox | 187 |
| Edge | 173 |
| Other | 90 |
| Browser | Visitors |
|---|---|
| Chrome | 275 |
| Safari | 200 |
| Firefox | 187 |
| Edge | 173 |
| Other | 90 |
Code
<!-- each browser keeps its slice as the order turns -->
<PieChart data={rows} {config} value="visitors" name="browser" animation={{ matchBy: matchByDataKey("browser") }} />
<!-- (items, t) => the slices to draw: each sweeps from its start angle -->
<PieChart data={rows} {config} value="visitors" name="browser" animation={{ interpolate: sweep }} />