Polar Area Chart

Pro

Nightingale rose / polar area chart with area-proportional (√) or linear radius scaling, padded wedges, labelled grid rings and a configurable start angle. Pure SVG.

</>sv-polar-chart chartpolarrosenightingaleradial
import { SvPolarChartComponent } from '@styloviz-pro/charts';

Demo & usage

Basic usage

Pro

Usage example — open the gallery for the full interactive demo.

Pro

An interactive demo for this component lives in the gallery.

Open live demo

More examples

Linear radius

Pro

Padded wedges

Pro

Sector interactions

Pro

When to use

  • Cyclical categories where the wrap-around matters — weekdays, months, compass bearings.
  • Comparing magnitudes across equal-width categories with a shared origin.
  • For non-cyclical categories, a bar chart is easier to read; for multi-series profiles, use the Radar chart.

Async states

  • loading
  • empty
  • error
  • retry

Inputs

NameTypeDefaultDescription
loadingbooleanfalseTrue while the sectors are being fetched.
errorSvDataError | string | nullnullLoad failure. Use `toSvDataError()` from `@styloviz/core` to normalize an `HttpErrorResponse`.
emptyMessagestring'No data to plot'Copy for the no-data state.
filteredbooleanfalseTrue when the emptiness is caused by a filter rather than an empty set.
sectorsreadonly PolarSector[][]Wedges to plot, drawn clockwise from `startAngle`.
valuePolicySvValuePolicy'omit'What to do with a sector this chart cannot plot — a negative value, `NaN`, `Infinity`. Radius is the encoding here, and there is no radius below the centre, so a negative has no honest wedge. It also reaches the share the tooltip and the data table quote, so leaving it in the sum would misstate every OTHER sector's percentage. - `omit` (default) — drop the wedge, and disclose the count. The remaining wedges each widen, since the slice is `360 / count`. - `reject` — refuse the dataset and show the error state. `clamp` is not supported: a wedge at radius zero has no area to mark, and the table would print a flat `0` indistinguishable from a real zero. It falls back to `omit` with a dev warning. `render` likewise.
maxValuenumber0Scale maximum. `0` (the default) rounds one out of the data.
scaleModePolarScaleMode'sqrt'How a value becomes a radius.
sizenumber300Chart diameter in pixels.
levelsnumber4Number of concentric grid rings.
padAnglenumber1Angular gap between wedges, in degrees.
startAnglenumber0Where the first wedge starts, in degrees clockwise from twelve o'clock.
showLabelsbooleantrueShow the labels around the rim.
showScalebooleantrueShow the value scale on the grid rings.
titlestring''Chart title, rendered above the plot.
ariaLabelstring''Accessible name override. Falls back to a generated summary.
customClassstring''Extra CSS classes applied to the root wrapper.

Outputs

EventPayload typeDescription
retryvoidThe host should re-run the failed load.
sectorHoverPolarSectorEventEmitted when a wedge is hovered or keyboard-focused.
sectorSelectPolarSectorEventEmitted when a wedge is clicked or activated with Enter/Space.

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

Pro

Bound to the names this component actually exposes.

Host class

Pro

Drive the three async inputs from your own fetch.

  • This component does not emit a query, so it renders what you give it. Fetch on your own trigger and bind `sectors`, `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

  • The shape of the rose depends on the order of the sectors, and the chart says so under the plot: every sector gets the same angular slice, so the silhouette is decided by which values sit next to each other. Under `linear` scaling it also states that area is not the value — a wedge's area grows with the square of its radius, so a doubled value covers four times the ink. `sqrt`, the default, is what keeps area proportional.
  • √ or linear radius scaling.
  • Grid ring count and value labels.
  • Pad angle between wedges and a custom start angle.
  • Per-sector colours.
  • `valuePolicy` decides what happens to a sector this chart cannot draw — a negative, `NaN` or `Infinity`. Radius is the encoding and there is no radius below the centre. `omit` (default) drops it and keeps it out of the share denominator; `reject` refuses the dataset. `clamp` is not offered: a wedge at the centre has no area to mark, and its table row would read as a genuine `0`, so a request for it falls back to `omit` with a dev warning.

Best practices

  • Do: Leave `scaleMode` at `sqrt` so the AREA encodes the value — that is what a reader compares.
  • Do: Order the sectors by their natural cycle, not by size.
  • Don't: Do not use `linear` unless the domain reads that way by convention; it makes a doubled value cover four times the space.
  • Tip: A single sector is drawn as a two-arc disc — one SVG arc cannot express a full revolution.

Accessibility

  • Every wedge is a keyboard-focusable `role="button"` named with its value and share of the total.
  • The plot is a labelled `role="group"`; Enter/Space emits `sectorSelect` and focus emits `sectorHover`.
  • Under the default √ scale wedge AREA is the value, which no reader can invert by eye. `sv-data-summary-table` publishes each sector's value and share of the total, in the cycle order the wedges are drawn in — the order is part of the data on a polar chart.
  • Whatever `valuePolicy` did is stated under the plot, not only in `console.warn`. An all-zero week is disclosed rather than replaced by the empty state: unlike a pie this chart still has its grid, its scale and every rim label, so all-zero is a legible picture of a real answer.

Feedback on Polar Area 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.

Loads giscus.app and GitHub — nothing is fetched until you click.