Skip to content

Pie Chart

ChartsSince 0.3.0
import { PieChart } from '@absoluteui/components/pie-chart';
import '@absoluteui/components/pie-chart/style.css';

Using Angular? See Pie Chart for Angular.

An accessible SVG pie or donut chart for one part-to-whole breakdown. It provides:

  • slices in data order, starting at 12 o’clock and running clockwise; an optional donut hole with a center label (the total by default);
  • printed percentage (or value) labels on slices large enough to hold them;
  • a legend listing every slice with its share, as toggle buttons;
  • keyboard-reachable slices (one tab stop, arrow keys) with a tooltip on focus and hover;
  • a generated summary and a data table (category, value, percent);
  • textures (with patterns), legend order, and labels as non-color cues (WCAG 1.4.1).

Negative and missing values cannot be drawn as slices: they are excluded from the pie and listed as “not plotted” in the summary and the table.

  • One breakdown of a total into a few (2-6) parts.
  • Donut: when the total (center label) matters as much as the parts.
  • Comparing many parts or similar sizes: use Bar Chart (lengths compare more accurately than angles).
  • Values that can be negative.
  • Comparing several breakdowns: use a stacked Bar Chart.
import { PieChart } from '@absoluteui/components/pie-chart';
const host = document.createElement('div');
document.body.append(host);
PieChart.create(host, {
label: 'Traffic sources',
slices: [
{ id: 'search', label: 'Search', value: 46 },
{ id: 'direct', label: 'Direct', value: 25 },
{ id: 'social', label: 'Social', value: 17 },
{ id: 'email', label: 'Email', value: 12 },
],
height: 240,
});
import { PieChart } from '@absoluteui/components/pie-chart';
const host = document.querySelector<HTMLElement>('#storage');
if (host) {
PieChart.create(host, {
label: 'Storage by type',
slices: [
{ id: 'docs', label: 'Documents', value: 120 },
{ id: 'media', label: 'Media', value: 310 },
{ id: 'backups', label: 'Backups', value: 90 },
],
donut: true,
centerLabel: '520 GB',
valueFormat: { style: 'unit', unit: 'gigabyte' },
sliceLabels: 'value',
});
}
import { PieChart } from '@absoluteui/components/pie-chart';
import '@absoluteui/components/pie-chart/style.css';
const host = document.querySelector<HTMLElement>('#sources');
if (host) {
PieChart.create(host, {
label: 'Traffic sources',
slices: [
{ id: 'search', label: 'Search', value: 46 },
{ id: 'direct', label: 'Direct', value: 25 },
],
valueFormat: { maximumFractionDigits: 0 },
});
}
import { PieChart } from '@absoluteui/components/pie-chart';
const host = document.createElement('div');
document.body.append(host);
PieChart.create(host, {
label: 'Plan mix',
slices: [
{ id: 'free', label: 'Free', value: 62 },
{ id: 'pro', label: 'Pro', value: 30 },
{ id: 'team', label: 'Team', value: 8 },
],
donut: true,
});
<div class="aui-chart aui-pie-chart [aui-pie-chart--donut] [aui-chart--patterns]">
<div class="aui-chart__header">title, description</div>
<ul class="aui-chart__legend" aria-label="Legend"><li><button aria-pressed="true">swatch, Search, 46%</button></li>...</ul>
<div class="aui-chart__body">
<svg class="aui-chart__svg" role="group" aria-roledescription="pie chart" aria-labelledby="T" aria-describedby="S">
<g class="aui-pie-chart__slices">
<g class="aui-pie-chart__slice-group aui-chart__series--c1">
<path class="aui-chart__mark aui-pie-chart__slice" role="img" aria-label="Search: 46 (46%)" tabindex="0"/>
<path class="aui-chart__pattern" aria-hidden="true"/>
</g>
</g>
<g class="aui-pie-chart__labels" aria-hidden="true">46%</g>
<text class="aui-pie-chart__center" aria-hidden="true">total</text> (donut)
</svg>
<div class="aui-chart__tooltip" aria-hidden="true" hidden/>
</div>
<p class="aui-chart__summary" hidden/> <div class="aui-chart__data">Show data table, table</div>
</div>
PieChart.create(host: HTMLElement, options: PieChartOptions): PieChart

Global configuration key: pieChart (see Configuration).

Option Type Default Description
label string Chart title: visible text and the accessible name of the plot (aria-labelledby). Required.
hideLabel boolean false Visually hide the title; it stays the accessible name.
description string Visible description below the title, also referenced by aria-describedby (text only).
summary string Replaces the generated accessible summary (aria-describedby).
valueFormat Intl.NumberFormatOptions Number format for values in tooltips, labels, the data table, the summary, and axis ticks (ticks use fixed fraction digits).
formatValue (value: number) => string Custom value text; overrides valueFormat everywhere except axis ticks.
hiddenSeries readonly string[] Ids of series (or slices) hidden initially; update() replaces the hidden set.
slices readonly PieChartSlice[] Slices: { id, label, value: number | null, color?: 1-8 }. Negative, null, and non-finite values are not plotted; they are listed in the summary and the table. Required.
donut boolean false Render a ring (inner radius 60%).
centerLabel string Donut center text. Default: the formatted total of visible slices; empty string: none. aria-hidden (the summary states the total).
valueLabel string Data table header of the value column. Default: localized “Value”.
legend 'auto' | 'show' | 'hide' "auto" auto: legend when there is more than one series (pie charts: always). Globally configurable.
dataTable 'toggle' | 'visible' | 'hidden' | 'none' "toggle" Data table fallback with the exact data: behind a Show data table button (built on first open), always visible, visually hidden (screen readers only), or none. Globally configurable.
tooltip boolean true Tooltip on pointer hover and keyboard focus. Globally configurable.
patterns boolean false Dash patterns and texture fills so series never differ by color alone. Off by default (plain colors); always on in forced colors. Turn it on when series are told apart by color alone (grouped or stacked series, multi-slice pies) and no labels carry the distinction (WCAG 1.4.1). Globally configurable.
height number 300 Plot height in CSS px (integer 120-2000); the width follows the container. Globally configurable.
sliceLabels 'percent' | 'value' | 'none' "percent" Text printed on slices large enough to hold it. Globally configurable.
locale string "en-US" Number, date, and message locale. Globally configurable. Inherited from common configuration.
direction 'ltr' | 'rtl' "ltr" rtl mirrors the category/x axis, the value axis side, and Left/Right arrow keys. Globally configurable. Inherited from common configuration.
Property Type Description
host HTMLElement The host element.
element SVGSVGElement The plot (svg role=“group”), named by the title and described by the summary.
summary string The generated (or custom) accessible summary.
hiddenSeries string[] Ids of hidden series (slices for Pie Chart).
Method Description
update(options: Partial<PieChartOptions>): void Merge, validate, and re-render. Invalid options throw and keep the previous state. Keyboard focus stays on the same data point.
setSeriesVisible(id: string, visible: boolean): void Show or hide a series (slice) programmatically; emits no event.
destroy(): void Remove rendering, host classes, listeners, the resize observer, and the configuration subscription.
Event Detail Bubbles Cancelable Description
aui-series-toggle { id: string; visible: boolean; hidden: string[] } Yes No The user toggled a legend entry (pointer or keyboard). Not emitted for update() or setSeriesVisible().

All rules live in the aui.components cascade layer, so application styles override them without specificity battles.

Class Purpose
aui-chart Host (shared chart chrome).
aui-pie-chart Host modifier for this chart type.
aui-chart--patterns patterns option on: dash patterns and textures shown.
aui-chart__header / __title / __title--hidden / __description Title and description.
aui-chart__legend / __legend-entry / __legend-item / __legend-item--hidden / __legend-label / __legend-detail Legend list and toggle buttons.
aui-chart__swatch aria-hidden legend and tooltip key (marker, dash, texture).
aui-chart__body / __svg / __layer Plot container (height from –aui-chart-height), SVG, and drawing layer.
aui-chart__grid / __gridline / __zero-line / __axis / __axis-line / __tick-label / __axis-title Axes (aria-hidden).
aui-chart__series--c1 ... --c8 Palette slot classes; set –aui-chart-color from color-chart-<n>.
aui-chart__dash--1 ... --4 / aui-chart__pattern / aui-chart__pattern-tile Dash patterns and texture overlays.
aui-chart__mark / __mark--active / __mark--hover Focusable data mark and its states.
aui-chart__value-label Printed values with a surface-colored halo.
aui-chart__tooltip / __tooltip-title / __tooltip-rows / __tooltip-row / __tooltip-label / __tooltip-value Tooltip (aria-hidden; the focused mark carries the same text).
aui-chart__empty Empty state text (No data, All series are hidden).
aui-chart__summary Hidden summary referenced by aria-describedby.
aui-chart__data / __data--hidden / __table-toggle / __table-scroll / __table / __cell--numeric Data table fallback.
aui-pie-chart--donut Donut modifier.
aui-pie-chart__slices / __slice-group / __slice / __labels / __center Slice marks, printed labels, and the donut center text.

Tokens this stylesheet reads (verified in CI). Override them in a theme or with the Theme Designer.

--aui-border-width | --aui-color-border | --aui-color-border-strong | --aui-color-chart-1 | --aui-color-chart-2 | --aui-color-chart-3 | --aui-color-chart-4 | --aui-color-chart-5 | --aui-color-chart-6 | --aui-color-chart-7 | --aui-color-chart-8 | --aui-color-chart-axis | --aui-color-chart-grid | --aui-color-focus-ring | --aui-color-hover | --aui-color-link | --aui-color-surface | --aui-color-surface-sunken | --aui-color-text | --aui-color-text-muted | --aui-duration-fast | --aui-easing-standard | --aui-focus-ring-offset | --aui-focus-ring-width | --aui-font-family-sans | --aui-font-size-md | --aui-font-size-sm | --aui-font-size-xl | --aui-font-size-xs | --aui-font-weight-medium | --aui-font-weight-regular | --aui-font-weight-semibold | --aui-line-height-normal | --aui-line-height-tight | --aui-radius-md | --aui-radius-sm | --aui-shadow-md | --aui-space-1 | --aui-space-2 | --aui-space-3 | --aui-tooltip-max-width | --aui-touch-target-min

interface PieChartSlice { id: string; label: string; value: number | null; color?: ChartColor }
interface PieChartConfig extends ChartBaseConfig { sliceLabels: 'percent' | 'value' | 'none' }
interface PieChartOptions extends ChartCommonOptions, Partial<PieChartConfig> {
slices: readonly PieChartSlice[];
donut?: boolean;
centerLabel?: string;
valueLabel?: string;
}

Pattern: SVG part-to-whole chart as a named, described group (role=“group” with aria-roledescription “pie chart” or “donut chart”) of role=“img” slices with roving focus; legend of toggle buttons with each share; data table fallback with value and percent columns.

Key Context Action
ArrowRight / ArrowDown Slice focused Next slice (clockwise); ArrowLeft/ArrowRight are swapped in RTL.
ArrowLeft / ArrowUp Slice focused Previous slice.
Home / End Slice focused First / last slice.
PageUp / PageDown Slice focused Ten slices back / forward.
Escape Tooltip visible Hides the tooltip without moving focus (WCAG 1.4.13); it returns on the next move.
Tab / Shift+Tab Any Legend buttons, then one tab stop for the plot (the active mark), then the Show data table button and table region.
Enter / Space Legend button Shows or hides the series (native button).
Element Role
svg.aui-chart__svg group with aria-roledescription (localized chart type), named by the title
data marks (points, bars, slices) img with an aria-label: category/x, series, formatted value
legend list (ul) named “Legend”; entries are toggle buttons (aria-pressed)
data table table (native) with caption, column headers, and row headers; wide tables scroll in a focusable region
axes, lines, textures, value labels, tooltip aria-hidden (decorative duplicates of the accessible data)
Attribute Element Value
aria-labelledby svg id of the visible (or visually hidden) title
aria-describedby svg description id (when provided) and the generated summary id
aria-roledescription svg Localized chart type, for example “line chart”
aria-label each mark Localized “{x}, {series}: {value}” (pie: “{label}: {value} ({percent})”)
tabindex active mark 0 on exactly one mark (roving); other marks have none
aria-pressed legend button true while the series is visible
aria-expanded / aria-controls Show data table button Table open state and the table region id

Roving focus: one mark is in the tab sequence and remembers the last visited data point, also across re-renders (resize, update). Toggling a legend entry keeps focus on its button; toggling the table keeps focus on the table button.

Criterion Level Note
1.1.1 Non-text Content A
1.3.1 Info and Relationships A
1.4.1 Use of Color A
1.4.3 Contrast (Minimum) AA
1.4.10 Reflow AA
1.4.11 Non-text Contrast AA
1.4.13 Content on Hover or Focus AA
2.1.1 Keyboard A
2.4.3 Focus Order A
2.4.7 Focus Visible AA
4.1.2 Name, Role, Value A

Automated test results: Accessibility and compliance.

  • The generated summary lists the chart type, series and point counts, axis ranges, per-series minimum and maximum with their positions, the overall trend, missing values, and hidden series.
  • Meaning never depends on color alone: marker shapes, dash patterns, and textures (patterns option), plus legend keys that repeat them.
  • Forced colors: series use CanvasText and keep shapes, dashes, and textures; focus uses Highlight.
  • No animation: nothing moves on render; hover and focus emphasis transitions are removed under prefers-reduced-motion and animation: none.
  • Slices are separated by a surface-colored stroke, so adjacent slices never depend on the contrast between two series colors.
  • Percentages are recomputed over visible slices when slices are hidden.
  • Manual screen-reader verification (NVDA, JAWS, VoiceOver, TalkBack) is pending.
  • aria-roledescription support varies; screen readers without it announce “group”.

default, donut, empty (“No data”: no slices, all values zero or not plotted), all slices hidden, slice hidden, slice focused (tooltip), slice hovered, table open.

From Trigger To
any legend button slice hidden or shown; shares recomputed over visible slices; aui-series-toggle
plot not focused Tab active slice focused, tooltip shown
slice focused arrow keys, Home, End another slice focused
tooltip visible Escape tooltip hidden
  • The summary lists the type, slice count, total, every plotted slice with value and percentage, not-plotted slices, and hidden slices.
  • Slices are separated by a color-surface stroke, so adjacent colors need no mutual contrast.
  • Forced colors: slices use CanvasText with Canvas textures; focus uses Highlight.
  • No animation. Manual screen-reader verification is pending.

The pie fits the smaller of the container width and height, centered; slice labels are printed only where they fit. Reflows at 320 CSS px.

Slices keep clockwise order (a pie has no reading axis); ArrowLeft/ArrowRight are swapped so “forward” follows the reading direction. Legend, tooltip, and table follow the document direction.

Slices use color-chart-1..8 by palette slot (3:1 against surface, background, and sunken surfaces in all themes).

configureAbsoluteUI({ components: { pieChart: { sliceLabels: 'value', dataTable: 'visible' } } });

Instance options override global and theme defaults. All options are dynamic.

All text uses textContent; SVG uses createElementNS; colors are classes. No innerHTML or style attributes.

No persistence, network access, or telemetry.

Budget: create with 12 slices under 15 ms including the first render (e2e performance test, median of 5).

Designed for up to about 12 slices; palette colors repeat after 8 (textures continue to differ).

  • A single plotted slice draws a full circle (100%).
  • Zero-value slices are listed but draw nothing; all zeros: “No data”.
  • Negative or missing values: excluded, listed as not plotted (“-5 (not plotted)”, “No value”).
  • Tiny slices (under about 17 degrees) get no printed label; the legend and tooltip still show their share.
Code Category Cause
PIE_CHART_OPTIONS configuration Missing label; slice ids not unique or empty; non-numeric values; invalid color, donut, centerLabel, or valueLabel.
CFG_INVALID_VALUE / CFG_UNKNOWN_OPTION configuration Invalid or unknown configuration.

A failed construction leaves the host untouched.

  • Negative values are not drawable.
  • Slices are in data order; sort before passing them if needed.
  • Manual screen-reader verification is pending.
  • Exploded slices, sunburst or multi-ring donuts, outside labels with leader lines.
  • Selection and export.