Pie Chart
Free4 variants: default pie, variable radius, custom legend template and smart labels. Optional largest-first ordering and long-tail grouping into a single Other slice. Pure SVG with entrance animations and hover effects.
import { SvDefaultPieChartComponent } from '@styloviz/charts';Demo & usage
Basic usage
Usage example — open the gallery for the full interactive demo.
An interactive demo for this component lives in the gallery.
Open live demoMore examples
Titled pie
<sv-default-pie-chart [slices]="slices" title="Market share" [size]="240" />
Click a slice
<sv-default-pie-chart [slices]="slices" (sliceSelect)="onSelect($event)" />
When to use
- Showing simple proportions of a single total with few segments.
- You want smart labels with connector lines.
- When comparison precision matters, prefer a Bar Chart.
Async states
- loading
- empty
- error
- retry
Inputs
| Name | Type | Default | Description |
|---|---|---|---|
| loading | boolean | false | True while the series are being fetched. |
| error | SvDataError | string | null | null | Load failure. Use `toSvDataError()` from `@styloviz/core` to normalize an `HttpErrorResponse`. |
| emptyMessage | string | 'No data to plot' | Copy for the empty state. |
| filtered | boolean | false | Whether a filter, not an absence of data, is why the chart is empty. |
| slices | PieSlice[] | [] | Pie slices. Each must have a label and a positive value. |
| valuePolicy | SvValuePolicy | 'omit' | What to do with a slice this chart cannot plot — a negative value, `NaN`, `Infinity`. A pie divides by the sum of its values, so an unplottable one is not merely undrawable: left in the denominator it changes the angle of every OTHER slice, which is why there is no "leave it alone" option here. - `omit` (default) — drop it, and disclose the count and that the percentages are of the remainder. - `reject` — refuse the dataset and show the error state. `clamp` is not supported: a clamped slice is a 0° arc, which leaves nothing to mark, so it falls back to `omit` with a dev warning. `render` likewise. |
| title | string | '' | Chart title displayed above the SVG. |
| size | number | 260 | Size of the SVG canvas (width = height). |
| options | DefaultPieChartOptions | {} | Chart options. |
| customClass | string | '' | Extra CSS classes on the root wrapper. |
| ariaLabel | string | '' | Accessible-name override for the chart image. When empty, a concise data summary is generated; the full data is exposed via a visually-hidden table. |
Outputs
| Event | Payload type | Description |
|---|---|---|
| retry | void | The host should re-run the failed load. |
| sliceSelect | PieSlice | Emitted when a slice (arc or legend entry) is clicked. |
<sv-default-pie-chart-pro>
Also in this family — SvDefaultPieChartProComponent from @styloviz-pro/charts.
Async states
- loading
- empty
- error
- retry
Inputs
| Name | Type | Default | Description |
|---|---|---|---|
| loading | boolean | false | True while the series are being fetched. |
| error | SvDataError | string | null | null | Load failure. Use `toSvDataError()` from `@styloviz/core` to normalize an `HttpErrorResponse`. |
| emptyMessage | string | 'No data to plot' | Copy for the empty state. |
| filtered | boolean | false | Whether a filter, not an absence of data, is why the chart is empty. |
| slices | PieSlice[] | [] | Pie slices. Each must have a label and a positive value. |
| valuePolicy | SvValuePolicy | 'omit' | What to do with a slice this chart cannot plot — a negative value, `NaN`, `Infinity`. A pie divides by the sum of its values, so an unplottable one is not merely undrawable: left in the denominator it changes the angle of every OTHER slice, which is why there is no "leave it alone" option here. - `omit` (default) — drop it, and disclose the count and that the percentages are of the remainder. - `reject` — refuse the dataset and show the error state. `clamp` is not supported: a clamped slice is a 0° arc, which leaves nothing to mark, so it falls back to `omit` with a dev warning. `render` likewise. |
| title | string | '' | Chart title displayed above the SVG. |
| size | number | 260 | Size of the SVG canvas (width = height). |
| options | DefaultPieChartOptions | {} | Chart options. |
| customClass | string | '' | Extra CSS classes on the root wrapper. |
| ariaLabel | string | '' | Accessible-name override for the chart image. When empty, a concise data summary is generated; the full data is exposed via a visually-hidden table. |
Outputs
| Event | Payload type | Description |
|---|---|---|
| retry | void | The host should re-run the failed load. |
| sliceSelect | PieSlice | Emitted when a slice (arc or legend entry) is clicked. |
<sv-pie-radius-chart>
Also in this family — SvPieRadiusChartComponent from @styloviz-pro/charts.
Async states
- loading
- empty
- error
- retry
Inputs
| Name | Type | Default | Description |
|---|---|---|---|
| loading | boolean | false | True while the series are being fetched. |
| error | SvDataError | string | null | null | Load failure. Use `toSvDataError()` from `@styloviz/core` to normalize an `HttpErrorResponse`. |
| emptyMessage | string | 'No data to plot' | Copy for the empty state. |
| filtered | boolean | false | Whether a filter, not an absence of data, is why the chart is empty. |
| slices | PieRadiusSlice[] | [] | Slices — each may include a `radius` multiplier (0.5–1.0). |
| valuePolicy | SvValuePolicy | 'omit' | What to do with a slice this chart cannot plot — a negative value, `NaN`, `Infinity`. A pie divides by the sum of its values, so an unplottable one is not merely undrawable: left in the denominator it changes the angle of every OTHER slice, which is why there is no "leave it alone" option here. - `omit` (default) — drop it, and disclose the count and that the percentages are of the remainder. - `reject` — refuse the dataset and show the error state. `clamp` is not supported: a clamped slice is a 0° arc, which leaves nothing to mark, so it falls back to `omit` with a dev warning. `render` likewise. |
| title | string | '' | Chart title. |
| size | number | 280 | SVG canvas size (square). |
| options | PieRadiusChartOptions | {} | Chart options. |
| customClass | string | '' | Extra CSS classes on the root wrapper. |
| ariaLabel | string | '' | Accessible-name override; otherwise a per-segment summary is generated. |
Outputs
| Event | Payload type | Description |
|---|---|---|
| retry | void | The host should re-run the failed load. |
<sv-pie-legend-template-chart>
Also in this family — SvPieLegendTemplateChartComponent from @styloviz-pro/charts.
Async states
- loading
- empty
- error
- retry
Inputs
| Name | Type | Default | Description |
|---|---|---|---|
| loading | boolean | false | True while the series are being fetched. |
| error | SvDataError | string | null | null | Load failure. Use `toSvDataError()` from `@styloviz/core` to normalize an `HttpErrorResponse`. |
| emptyMessage | string | 'No data to plot' | Copy for the empty state. |
| filtered | boolean | false | Whether a filter, not an absence of data, is why the chart is empty. |
| slices | PieSlice[] | [] | Pie slices — may include optional `description` for legend. |
| valuePolicy | SvValuePolicy | 'omit' | What to do with a slice this chart cannot plot — a negative value, `NaN`, `Infinity`. A pie divides by the sum of its values, so an unplottable one is not merely undrawable: left in the denominator it changes the angle of every OTHER slice, which is why there is no "leave it alone" option here. - `omit` (default) — drop it, and disclose the count and that the percentages are of the remainder. - `reject` — refuse the dataset and show the error state. `clamp` is not supported: a clamped slice is a 0° arc, which leaves nothing to mark, so it falls back to `omit` with a dev warning. `render` likewise. |
| title | string | '' | Chart title. |
| size | number | 240 | SVG canvas size (square). |
| options | PieLegendTemplateOptions | {} | Chart options. |
| customClass | string | '' | Extra CSS classes on the root element. |
| ariaLabel | string | '' | Accessible-name override; otherwise a per-segment summary is generated. |
Outputs
| Event | Payload type | Description |
|---|---|---|
| retry | void | The host should re-run the failed load. |
<sv-smart-labels-pie-chart>
Also in this family — SvSmartLabelsPieChartComponent from @styloviz-pro/charts.
Async states
- loading
- empty
- error
- retry
Inputs
| Name | Type | Default | Description |
|---|---|---|---|
| loading | boolean | false | True while the series are being fetched. |
| error | SvDataError | string | null | null | Load failure. Use `toSvDataError()` from `@styloviz/core` to normalize an `HttpErrorResponse`. |
| emptyMessage | string | 'No data to plot' | Copy for the empty state. |
| filtered | boolean | false | Whether a filter, not an absence of data, is why the chart is empty. |
| slices | PieSlice[] | [] | Pie slices. |
| valuePolicy | SvValuePolicy | 'omit' | What to do with a slice this chart cannot plot — a negative value, `NaN`, `Infinity`. A pie divides by the sum of its values, so an unplottable one is not merely undrawable: left in the denominator it changes the angle of every OTHER slice, which is why there is no "leave it alone" option here. - `omit` (default) — drop it, and disclose the count and that the percentages are of the remainder. - `reject` — refuse the dataset and show the error state. `clamp` is not supported: a clamped slice is a 0° arc, which leaves nothing to mark, so it falls back to `omit` with a dev warning. `render` likewise. |
| title | string | '' | Chart title. |
| svgWidth | number | 520 | SVG canvas width. |
| svgHeight | number | 300 | SVG canvas height. |
| options | SmartLabelsOptions | {} | Chart options. |
| customClass | string | '' | Extra CSS classes on the root wrapper. |
| ariaLabel | string | '' | Accessible-name override; otherwise a per-segment summary is generated. |
Outputs
| Event | Payload type | Description |
|---|---|---|
| retry | void | The host should re-run the failed load. |
Wire it to your API
This component is headless about transport: it renders what you give it and reports what the user asks for. Nothing below requires @styloviz/data — drive it from whatever you already use.
Template
Bound to the names this component actually exposes.
<sv-default-pie-chart [slices]="data.items()" [loading]="data.loading()" [error]="data.error()" [filtered]="data.filtered()" (retry)="data.reload()" />
Host class
Drive the three async inputs from your own fetch.
// This component reports its state but does not emit a query, so drive // it from your own fetch and bind the three async inputs. readonly items = signal<Row[]>([]); readonly loading = signal(false); readonly error = signal<SvDataError | null>(null); async load(): Promise<void> { this.loading.set(true); this.error.set(null); try { this.items.set(await this.api.fetchRows()); } catch (e) { this.error.set(toSvDataError(e)); } finally { this.loading.set(false); } }
- This component does not emit a query, so it renders what you give it. Fetch on your own trigger and bind `slices`, `loading` and `error`.
- Set `filtered` when a search or filter is active. It is the difference between "you have no orders" and "no orders match this filter" — telling a customer with 4,000 orders the first one reads as a bug.
- Normalize failures with `toSvDataError()` from `@styloviz/core`. It derives `retryable` from the status, so a 404 does not get a "Try again" button that can only fail again.
Full walkthrough: Connecting to a backend.
Customization & theming
- Fixed or variable-radius slices. The radius is EMPHASIS ONLY — the angle carries the value — and the chart says so under the plot whenever a radius is actually varied, with the area cost named: a sector's area grows with the square of its radius, so a slice pulled in to 0.7 covers about half the area its share would occupy at full radius.
- `sliceOrder`: keep the host's order (default) or sort largest first, which is the arrangement a pie is easiest to read in — the eye compares neighbouring arcs rather than arcs on opposite sides of the circle.
- `groupBelow` and `maxSlices` fold the unreadable tail into one `Other` slice and disclose how many and what share. Off by default, because folding a host's categories is a decision about their data; a single small slice is never folded, since an `Other` of one is that slice with its name taken away.
- Smart auto-positioned labels with connectors.
- Custom legend templates.
- Handle `sliceSelect` (arc or legend click) for selection.
- `valuePolicy` decides what happens to a slice this chart cannot plot — a negative, `NaN` or `Infinity`. A pie divides by the sum of its values, so an unplottable one is not merely undrawable: left in the denominator it changes the angle of every OTHER slice, which is why there is no "leave it alone" option. `omit` (default) drops it and says the percentages are of the remainder; `reject` refuses the dataset. `clamp` is not offered: a clamped slice is a 0° arc, which leaves nothing to mark, so a request for it falls back to `omit` with a dev warning. All four pie treatments take it.
Best practices
- Do: Sort slices largest-to-smallest for an intuitive read.
- Don't: Don't exceed ~5–6 slices; small wedges become unreadable.
- Tip: Use the Donut variant when you need a center total.
Accessibility
- The SVG is a `role="group"` with a generated label listing each segment and its share (override via `ariaLabel`) — `group`, not `img`, so that focusable slices are not pruned out of the accessibility tree with the rest of an `img`'s subtree.
- Arc angle is share and the raw value is nowhere else on the page, so `sv-data-summary-table` publishes segment, value and percentage — on all four pie treatments (default, smart labels, radius, legend template). No overview line: the generated name has already read every label with its share, so a summary sentence there is that sentence again.
- Slice labels and values are real text; the hover state has a non-color cue.
- Whatever `valuePolicy` does to the data is stated in the rendered output, under the plot and under the empty state — how many slices were dropped, their real values, and that the shares are of what remains. A `console.warn` is not a disclosure: the person reading the dashboard never sees it.
- A pie whose every value is zero shows the empty state rather than a blank circle, and the sentence beneath distinguishes "the data arrived and was all zero" from "the fetch returned nothing".
- Grouping is disclosed in the rendered output — how many slices were folded, which ones, and what share they came to — and the summary table lists each folded slice in its own row under `Other`, marked `(in Other)`, so the aggregate never hides the detail from a reader using the table. `Other` is drawn in a neutral slate, not the colour of the first slice it folded, and on the radius pie at the value-weighted radius of its members rather than full emphasis.
Feedback on Pie Chart
Spotted a gap in this page, or something that didn't work as described? Comments are GitHub Discussions in the public styloviz/community repo, so posting needs a GitHub account.