Radar Chart
import { RadarChart } from '@absoluteui/components/radar-chart';import '@absoluteui/components/radar-chart/style.css';Using Angular? See Radar Chart for Angular.
What it does
Section titled “What it does”An accessible SVG radar (polar) chart that compares series across several quantitative axes arranged clockwise around a circle, starting at the top. It provides:
- one closed polygon per series (translucent fill with
fill), with a focusable vertex per axis; - a shared radial scale with rings, spokes, and ring tick labels (all
aria-hidden); - keyboard navigation around the axes (Left/Right) and between series (Up/Down), with a tooltip on focus and hover;
- a legend of toggle buttons, a generated summary, and a data table (one row per axis);
- marker shapes and dash patterns (with
patterns) as non-color cues (WCAG 1.4.1).
Axes keep clockwise order in RTL, like pie charts. Nothing animates.
When to use
Section titled “When to use”- Comparing the profile of 1-5 items across 3-12 comparable measures on the same scale (skills, product attributes, scores).
When not to use
Section titled “When not to use”- Precise comparison of values: use Bar Chart (grouped).
- Measures on different scales or units (the scale is shared).
- Many series (polygons overlap) or ordered data such as time: use Line Chart.
Examples
Section titled “Examples”Two profiles on a fixed scale with series toggling
Section titled “Two profiles on a fixed scale with series toggling”import { RadarChart, type RadarChartSeriesToggleDetail } from '@absoluteui/components/radar-chart';
const host = document.createElement('div');document.body.append(host);const chart = RadarChart.create(host, { label: 'Candidate skills', axes: ['Design', 'Frontend', 'Backend', 'Testing', 'Operations'], series: [ { id: 'ana', label: 'Ana', values: [4, 5, 3, 4, 2] }, { id: 'ben', label: 'Ben', values: [2, 3, 5, 3, 4] }, ], valueAxis: { min: 0, max: 5, tickCount: 5 },});host.addEventListener('aui-series-toggle', (event) => { const { hidden } = (event as CustomEvent<RadarChartSeriesToggleDetail>).detail; host.dataset.hidden = hidden.join(',');});chart.setSeriesVisible('ben', false);Unfilled polygons with percent values
Section titled “Unfilled polygons with percent values”import { RadarChart } from '@absoluteui/components/radar-chart';
const host = document.querySelector<HTMLElement>('#coverage');if (host) { RadarChart.create(host, { label: 'Test coverage by module', axes: ['Auth', 'Billing', 'Search', 'Reports', 'Admin', 'API'], series: [ { id: 'unit', label: 'Unit', values: [0.9, 0.75, 0.6, null, 0.8, 0.95], color: 1 }, { id: 'e2e', label: 'End-to-end', values: [0.6, 0.5, 0.4, 0.3, 0.2, 0.7], color: 4 }, ], valueAxis: { min: 0, max: 1 }, valueFormat: { style: 'percent' }, fill: false, dataTable: 'visible', });}import { RadarChart } from '@absoluteui/components/radar-chart';import '@absoluteui/components/radar-chart/style.css';
const host = document.querySelector<HTMLElement>('#products');if (host) { RadarChart.create(host, { label: 'Product comparison', axes: ['Price', 'Quality', 'Support', 'Features', 'Speed'], series: [ { id: 'ours', label: 'Ours', values: [7, 8, 9, 6, 8] }, { id: 'rival', label: 'Rival', values: [8, 6, 5, 8, 7] }, ], valueAxis: { min: 0, max: 10 }, });}More usage
Section titled “More usage”import { RadarChart } from '@absoluteui/components/radar-chart';
const host = document.createElement('div');document.body.append(host);RadarChart.create(host, { label: 'Skills', axes: ['Speed', 'Power', 'Range', 'Armor'], series: [ { id: 'a', label: 'Alpha', values: [3, 5, 2, 4] }, { id: 'b', label: 'Beta', values: [4, 2, 5, 1] }, ],});Anatomy
Section titled “Anatomy”<div class="aui-chart aui-radar-chart [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, Alpha</button></li>...</ul> <div class="aui-chart__body"> <svg class="aui-chart__svg" role="group" aria-roledescription="radar chart" aria-labelledby="T" aria-describedby="S"> <g class="aui-chart__grid" aria-hidden="true">rings (aui-radar-chart__ring), spokes</g> <g class="aui-chart__axis" aria-hidden="true">ring ticks, axis names (aui-radar-chart__axis-label)</g> <g class="aui-radar-chart__series-layer"> <g class="aui-radar-chart__series aui-chart__series--c1" aria-hidden="true"><path class="aui-chart__area"/><path class="aui-chart__line aui-chart__dash--1"/></g> </g> <g class="aui-radar-chart__points"> <g class="aui-radar-chart__series aui-chart__series--c1"> <path class="aui-chart__point aui-chart__mark" role="img" aria-label="Speed, Alpha: 3" tabindex="0"/>... </g> </g> </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>API reference
Section titled “API reference”Factory
Section titled “Factory”RadarChart.create(host: HTMLElement, options: RadarChartOptions): RadarChartGlobal configuration key: radarChart (see Configuration).
Options
Section titled “Options”| Option | Type | Default | Description |
|---|---|---|---|
label |
string |
Chart title: visible text and the accessible name of the plot (aria-labelledby); also the data table caption. 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 (axes, scale, each series’ highest and lowest axis, hidden series). | |
valueFormat |
Intl.NumberFormatOptions |
Number format for values in tooltips, vertex labels, the data table, the summary, and ring ticks (ticks use fixed fraction digits). | |
formatValue |
(value: number) => string |
Custom value text; overrides valueFormat everywhere except ring ticks. | |
hiddenSeries |
readonly string[] |
Ids of series hidden initially; update() replaces the hidden set. | |
axes |
readonly string[] |
Axis names, clockwise from the top. At least three. Required. | |
series |
readonly ChartSeries[] |
Series: { id, label, values: (number | null)[], color?: 1-8 } with exactly one value per axis. null, NaN, and infinities are drawn at the center and read “No value”. Required. | |
valueAxis |
RadarChartValueAxis |
Shared radial scale { min?, max?, tickCount? (2-20, default 4 rings) }. min defaults to 0, or the data minimum when negative; max to the data maximum; nice-rounded unless min or max is fixed. label and includeZero are validated but not used by the radar chart. | |
legend |
'auto' | 'show' | 'hide' |
"auto" |
auto: legend of toggle buttons when there is more than one series. Globally configurable. |
dataTable |
'toggle' | 'visible' | 'hidden' | 'none' |
"toggle" |
Data table fallback (one row per axis, one column per series): 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 on the polygon outlines so series never differ by color alone (always on in forced colors); marker shapes differ regardless. Globally configurable. |
height |
number |
300 |
Plot height in CSS px (integer 120-2000); the width follows the container. Globally configurable. |
fill |
boolean |
true |
Fill each polygon with a translucent (12%) series color; the outline and vertices carry the data. Globally configurable. |
locale |
string |
"en-US" |
Number and message locale. Globally configurable. Inherited from common configuration. |
direction |
'ltr' | 'rtl' |
"ltr" |
Axes keep clockwise order in RTL (like pie charts); rtl swaps ArrowLeft/ArrowRight so forward follows the reading direction. Globally configurable. Inherited from common configuration. |
Properties
Section titled “Properties”| 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, in data order. |
Methods
Section titled “Methods”| Method | Description |
|---|---|
update(options: Partial<RadarChartOptions>): void |
Merge, validate, and re-render. Invalid options throw and keep the previous state. Keyboard focus stays on the same vertex. |
setSeriesVisible(id: string, visible: boolean): void |
Show or hide a series programmatically; emits no event. |
destroy(): void |
Remove rendering, host classes, listeners, the resize observer, and the configuration subscription. |
Events
Section titled “Events”| 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(). |
CSS classes
Section titled “CSS classes”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-radar-chart |
Host modifier for this chart type. |
aui-chart--patterns |
patterns option on: dash patterns shown. |
aui-chart__header / __title / __title--hidden / __description |
Title and description. |
aui-chart__legend / __legend-entry / __legend-item / __legend-item--hidden / __legend-label |
Legend list and toggle buttons. |
aui-chart__swatch |
aria-hidden legend and tooltip key (marker and dash). |
aui-chart__body / __svg / __layer |
Plot container (height from –aui-chart-height), SVG, and drawing layer. |
aui-chart__grid / __gridline / aui-radar-chart__ring |
Rings and spokes (aria-hidden). |
aui-chart__axis / __tick-label / aui-radar-chart__axis-label |
Ring tick labels and axis names (aria-hidden). |
aui-chart__series--c1 ... --c8 |
Palette slot classes; set –aui-chart-color from color-chart-<n>. |
aui-radar-chart__series-layer / __series / __points |
Polygon groups (aria-hidden) and the vertex groups. |
aui-chart__area / __line / __dash--1 ... --4 |
Translucent polygon fill, outline, and dash patterns. |
aui-chart__point |
Vertex marker (shape by series position). |
aui-chart__mark / __mark--active / __mark--hover |
Focusable vertex and its states. |
aui-chart__tooltip / __tooltip-title / __tooltip-rows / __tooltip-row / __tooltip-label / __tooltip-value |
Tooltip (aria-hidden; the focused vertex 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. |
Design tokens
Section titled “Design tokens”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-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
TypeScript definitions
Section titled “TypeScript definitions”interface RadarChartConfig extends ChartBaseConfig { fill: boolean }interface RadarChartValueAxis { label?: string; min?: number; max?: number; tickCount?: number; includeZero?: boolean }interface RadarChartOptions extends ChartCommonOptions, Partial<RadarChartConfig> { axes: readonly string[]; series: readonly ChartSeries[]; valueAxis?: RadarChartValueAxis;}type RadarChartSeriesToggleDetail = { id: string; visible: boolean; hidden: string[] };Accessibility
Section titled “Accessibility”Pattern: SVG radar chart as a named, described group (role=“group” with aria-roledescription “radar chart”) of role=“img” vertices with two-dimensional roving focus (around the axes, between series); legend of toggle buttons; data table fallback with one row per axis.
Keyboard
Section titled “Keyboard”| Key | Context | Action |
|---|---|---|
| ArrowRight / ArrowLeft | Vertex focused | Next (clockwise) / previous axis of the same series; swapped in RTL so forward follows the reading direction. |
| ArrowDown / ArrowUp | Vertex focused | Same axis in the next / previous visible series (single visible series: next / previous axis). |
| Home / End | Vertex focused | First (top) / last axis of the series. |
| PageUp / PageDown | Vertex focused | Ten axes back / forward (clamped to the ends). |
| 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 vertex), 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 “radar chart” (localized), named by the title |
| vertices (path.aui-chart__point) | img with an aria-label: axis, series, formatted value |
| legend | list (ul) named “Legend”; entries are toggle buttons (aria-pressed) |
| data table | table (native) with caption, column headers (Axis, then each series), and row headers (axes); wide tables scroll in a focusable region |
| rings, spokes, tick labels, axis names, polygons, tooltip | aria-hidden (decorative duplicates of the accessible data) |
ARIA attributes
Section titled “ARIA attributes”| 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 “radar chart” |
aria-label |
each vertex | Localized “{axis}, {series}: {value}”, for example “Power, Beta: 2”; missing values read “No value” |
tabindex |
active vertex | 0 on exactly one vertex (roving); other vertices 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 vertex is in the tab sequence and remembers the last visited vertex, also across re-renders (resize, update, series toggles). Toggling a legend entry keeps focus on its button; toggling the table keeps focus on the table button.
WCAG 2.2 success criteria addressed
Section titled “WCAG 2.2 success criteria addressed”Automated test results: Accessibility and compliance.
Notes and known caveats
Section titled “Notes and known caveats”- The generated summary lists the type, series and axis counts, the axis names in order, the scale, each series’ highest and lowest axis, and hidden series, for example “radar chart, 2 series, 4 axes: Speed, Power, Range, and Armor. Scale {from} to {to}. Alpha: highest 5 on Power, lowest 2 on Range. …”
- Meaning never depends on color alone: series differ by marker shape and (with patterns) dash pattern, and the legend keys repeat them.
- Axes keep clockwise order in RTL (a radar has no reading axis, like pie charts); only ArrowLeft/ArrowRight are swapped.
- Missing values are drawn at the center and read “No value”.
- Forced colors: series use CanvasText and keep shapes and dashes; axis names use CanvasText; focus uses Highlight.
- No animation.
- Manual screen-reader verification (NVDA, JAWS, VoiceOver, TalkBack) is pending.
- aria-roledescription support varies; screen readers without it announce “group”.
- Polygon area depends on axis order and exaggerates differences; the summary and table give exact values.
Behavior
Section titled “Behavior”States
Section titled “States”default, unfilled (fill: false), empty (“No data”: no series or no finite values), all series hidden (“All series are hidden”), series hidden, vertex focused (tooltip), vertex hovered, table open.
State transitions
Section titled “State transitions”| From | Trigger | To |
|---|---|---|
| any | legend button | series hidden or shown; scale recomputed over visible series; aui-series-toggle |
| plot not focused | Tab | active vertex focused, tooltip shown |
| vertex focused | arrow keys, Home, End, PageUp, PageDown | another vertex focused |
| tooltip visible | Escape | tooltip hidden |
Accessibility notes
Section titled “Accessibility notes”- The summary lists the type, counts, the axis names in order, the scale, each series’ highest and lowest axis, and hidden series: “radar chart, 2 series, 4 axes: Speed, Power, Range, and Armor. Scale … Alpha: highest 5 on Power, lowest 2 on Range. …”
- Series differ by color, marker shape, and (with
patterns) dash pattern; legend keys repeat them. - Missing values are drawn at the center and read “No value”.
- Forced colors: series use
CanvasTextand keep shapes and dashes; focus usesHighlight. - No animation. Manual screen-reader verification is pending.
Responsive behavior
Section titled “Responsive behavior”The width follows the container (ResizeObserver); the height is height. The radius fits the smaller dimension after reserving room for the axis names, which are truncated when space is short. Reflows at 320 CSS px.
Right-to-left
Section titled “Right-to-left”Axes keep clockwise order from the top in RTL (a radar has no reading axis, like pie charts; decision C5). ArrowLeft/ArrowRight are swapped so “forward” follows the reading direction. The legend, tooltip, and table follow the document direction.
Theming
Section titled “Theming”Series colors come from color-chart-1..8 by palette slot (series position, or color); each meets 3:1 against surfaces in all shipped themes. The 12% fill is decorative; outlines and vertices carry the data.
Global configuration
Section titled “Global configuration”configureAbsoluteUI({ components: { radarChart: { fill: false, height: 360 } } });Changes apply to existing instances immediately.
Component configuration
Section titled “Component configuration”Instance options override global and theme defaults. All options are dynamic.
Security
Section titled “Security”All text uses textContent; SVG uses createElementNS; colors are classes. No innerHTML or style attributes.
Data handling
Section titled “Data handling”No persistence, network access, or telemetry.
Performance
Section titled “Performance”Budget: RadarChart.create with 5 series x 12 axes < 30 ms in headless Chromium (e2e performance test), including the first render.
Supported data scale
Section titled “Supported data scale”Up to about 5 series and 12 axes; more work but polygons overlap and labels crowd.
Edge cases
Section titled “Edge cases”- Missing values (
null,NaN, infinities): the vertex is at the center and reads “No value”. - Values outside a fixed
valueAxis.min/maxare clamped to the center or the outer ring; labels and table keep the real value. - Negative data: the scale starts at the data minimum.
- Hiding series recomputes the scale over the visible series; all hidden: “All series are hidden”.
Errors
Section titled “Errors”| Code | Category | Cause |
|---|---|---|
RADAR_CHART_OPTIONS |
configuration | Missing label; fewer than 3 axes or non-string axes; series ids not unique or empty; values not one per axis or non-numeric; invalid color, valueAxis (non-finite, max <= min, tickCount outside 2-20), or formatters. |
CFG_INVALID_VALUE / CFG_UNKNOWN_OPTION |
configuration | Invalid or unknown configuration. |
A failed construction leaves the host untouched.
Known limitations
Section titled “Known limitations”- One shared radial scale; no per-axis scales.
- Missing values collapse to the center instead of leaving a gap.
- Manual screen-reader verification is pending.
Unsupported scenarios
Section titled “Unsupported scenarios”- Per-axis scales or units; polar area (rose) and radial bar charts.
- Selection and brushing.