Skip to content

PieChart

Shows parts of a whole as slices of a circle. It answers one question well (is one of these most of it?), and everything finer than that belongs in a bar chart.

tsx
import { PieChart } from 'neba';

<PieChart
  label="Sessions by traffic source"
  shape="donut"
  categories={['Organic', 'Direct', 'Paid']}
  data={[18420, 9260, 6140]}
/>;

The data

A pie has one series, so it takes data directly rather than an array of series. The slices are the entities here: each one takes a palette slot of its own, and the legend lists them.

data is an array of NebaChartDatum: a number, a null, or a point that carries its own name and colour. categories names the slices; points may carry their own x instead.

tsx
<PieChart categories={['Free', 'Pro', 'Team']} data={[4820, 2140, 890]} />

<PieChart
  data={[
    { x: 'Passed', y: 1284, color: 'success' },
    { x: 'Failed', y: 96, color: 'danger' }
  ]}
/>

Slices are drawn in the order they are given and are not re-sorted, so a chart that is refiltered keeps every category the colour and the position it had.

Props

PropTypeDefaultDescription
data * NebaChartDatum[]The slices. A pie has one series, so it takes the values directly: the slices are the entities here
categories(string | number | Date)[]What each slice is called. Points may carry their own x instead
shape'pie' | 'donut' | 'semi''pie'pie is a filled disc, donut opens a hole for the total, semi draws half a ring from the bottom of the box
startAnglenumber0Where the first slice starts, in degrees clockwise from twelve o’clock. Ignored by semi
centerReactNodeWhat goes in the hole. A ring with nothing in the middle is a pie with a bite out of it
valueLabels'none' | 'all''none'Writes each slice's share on it, only where the text fits with room on both sides. One that does not fit is dropped rather than clipped
variantshared'solid' | 'outline' | 'text''text'Weight of the surface. A chart is a drawing rather than a sheet, so this defaults to text and a chart inside a Card draws no second edge. Use outline for one that stands alone
sizeshared'xs' | 'sm' | 'md' | 'lg' | 'xl''md'Axis type, line weight, marker size, and the height, when none is given
colorshared'primary' | 'secondary' | 'success' | 'warning' | 'danger' | 'info''primary'The sheet's colour family. A series' colour does not come from here: the palette or series.color decides that
densityshared'default' | 'compact''default'Padding only: never the height, never the type scale
elevationshared0 | 1 | 2 | 30Drop shadow depth. 0 means no shadow at all
heightnumber | stringsizeHow tall the drawing is. The axis labels are drawn inside it, so a card sized to the chart is a card the chart fits in
labelstringlocale's wordThe chart's accessible name. Read out in place of the drawing, and the caption of the hidden data table under it. Without it the locale's generic word stands in, but what the chart is *of* can only be said here
formatIntl.NumberFormatOptionsHow numbers are written everywhere they appear: the axis, the tooltip, the value labels, the table. Without it, past ten thousand they are compacted (12.4K)
localestringThe language of the chart's own words and dates
legendboolean | NebaChartLegendseries ≥ 2Shown automatically from two series up and left off below that: a legend with one swatch restates the title
tooltipboolean | NebaChartTooltiptrueWhat the pointer uncovers. It never carries a value that is not also in the hidden table
emptyReactNodeWhat to draw when there is nothing to draw

Every native <div> attribute passes through, along with every Box prop. legend and tooltip take the same shapes they take on LineChart. See prop conventions for the shared axes.

Examples

shape

pie is a filled disc. donut opens a hole for the total. semi draws half a ring from the bottom of the box, which fits a dashboard tile that is wider than it is tall.

center

Whatever goes in the hole of a donut or a semi. A ring with nothing in the middle is a pie with a bite out of it; the total, or the one figure the chart is about, is what it was drawn around.

tsx
<PieChart shape="donut" center={<Typography level="h4">38.6K</Typography>}  />

valueLabels

all writes each slice's share on it: a share is what a pie is a picture of, and the value is one hover away. A label is only drawn where the slice is wide enough for the text with room on both sides; one that does not fit is dropped rather than clipped, and the tooltip and the table still have it.

Colour

Slices take palette slots in the order they are passed. A point's own color overrides that, which is the right move when the slices mean something: passed and failed are not "series one" and "series two".

legend · startAngle

The legend appears from two slices up and is interactive by default: clicking a slice's entry removes it and the rest renormalise to fill the circle. startAngle turns the whole thing, in degrees clockwise from twelve o'clock.

tsx
<PieChart legend={{ side: 'right', align: 'center' }} startAngle={-30}  />

Accessibility

  • The data is also rendered as a visually hidden table, captioned with label.
  • The plot is focusable; and step between slices and Escape clears the selection, so the tooltip is reachable without a pointer.
  • Slices are separated by a gap of the surface colour, sized to stay 2px on screen at any radius, rather than by a stroke around each one.

When not to use it

An angle is a poor thing to compare: two slices within a few percent of each other are indistinguishable, and no reader can rank six of them. Past six slices, or when the question is "how do these rank", use a BarChart. A two-slice pie is a Statistic.

Released under the MIT License