Show a share-of-total with a pie chart

By the end of this recipe you'll have a clean 4-slice pie with an outside-label-and-leader-line legend — the right shape for "what proportion went where, totalling 100%?".

Charts Intermediate ~10 min React · @corelithzw/react

Overview

Slices of a circle summing to one. Each slice's angle is its share of the total. The legend names what each colour means.

Pies answer "who got what fraction of one whole?" — sales mix by region, vote share, time spent per category. They're the chart most often misused — usually because the data wasn't really a parts-of-whole. If your values don't sum to a meaningful whole, a bar chart is more honest.

Skip pies above 4 slices (small-angle reads are unreliable), when slice sizes are within a few percentage points of each other (bars beat pies for fine comparison), or when there's no headline number — at that point switch to a donut and use the centre.

Default opinion: if you can write the value next to the slice without crowding, you have a usable pie. If you can't, you have too many slices.

The chart

Sales share by region this quarter. Four slices, labelled outside with their share.

Sales by region, Q2 Four slices: Harare 42%, Bulawayo 26%, Mutare 19%, Other 13%. Harare · 42% Bulawayo · 26% Mutare · 19% Other · 13% Region totals Harare$42,000 Bulawayo$26,000 Mutare$19,000 Other$13,000 Total$100,000
Harare leads at $42,000 (42%); Bulawayo $26,000; Mutare $19,000; the remaining smaller regions combined $13,000.

Required pieces

From @corelithzw/react.

Intended exports used here: Chart.Pie, Chart.Legend.

Roadmap. Chart.Pie ships in @corelithzw/react v0.2.

The React snippet

Same prop shape as Chart.Donut minus the centre slot.

SalesByRegion.tsx@corelithzw/react

Customising

Three forks.

Inside labels

Put percentages inside the slices when the chart sits next to a legend that already names them.

<Chart.Pie
  data={slices}
  labels="inside"
  labelFormat={(s) => `${Math.round(s.pct * 100)}%`}
  height={280}
/>

Sort slices

Largest slice at the top, then clockwise descending. The reader's eye reads ranking before names.

<Chart.Pie
  data={slices.sort((a, b) => b.sales - a.sales)}
  startAngle={-90}     {/* top */}
  height={280}
/>

Highlight one slice

Pull the focal slice outward by a few pixels. Reserve for the slice the page is actually about.

<Chart.Pie
  data={slices}
  emphasis="Harare"
  emphasisOffset={8}
  height={280}
/>

In context

Inside a row card on a tablet report — pie + legend share one row.

Sales by region · Q2
$100k total
Harare alone accounts for 42% of Q2 sales. Combined, the three named cities cover 87%.

Accessibility

Pies are radial — same a11y headaches as donuts.

  • Role and label. Root <svg> uses role="img" + aria-labelledby on <title> + <desc>.
  • Per-slice labels. Each <path> sits in a <g aria-label="Harare: 42 percent, $42,000">.
  • SR summary. A .ck-sr-only paragraph ranks slices and notes the long tail.
  • Leader lines repeat the legend. Don't rely on colour alone — every slice has a written percentage either inside or via a leader line.
  • Keyboard. Each slice is tabindex="0"; Arrow keys walk clockwise.