# Radar Chart

> Several series compared across the same axes, as polygons on a polar grid or as polar-area wedges.

Source: https://ngwr.dev/charts/radar-chart  
Added in v15.1

## Installation

Import the class, and `@use` the entry point in your global styles: without it the component renders unstyled.

```typescript
import { Component } from '@angular/core';
import { WrRadarChart } from 'ngwr/charts/radar-chart';

@Component({ imports: [WrRadarChart] })
export class MyComponent {}
```

```scss
@use 'ngwr/charts/radar-chart';
```

## Basic

One value per axis per series. The first axis points up and the rest follow clockwise.

```angular-html
<wr-radar-chart
  [axes]="['Speed', 'Power', 'Range', 'Comfort', 'Price']"
  [series]="[
    { label: 'Model A', data: [80, 65, 70, 90, 55] },
    { label: 'Model B', data: [60, 85, 75, 60, 80] }
  ]"
  [max]="100"
/>
```

## Scale

With no `max` the scale runs from zero to a readable step above the data. A fixed `max` gets rings on a readable step that divides it: a rating out of 5 has one per point.

```angular-html
<!-- Fitted: 0 to a readable step above the data -->
<wr-radar-chart [axes]="axes" [series]="models" />

<!-- Fixed: a rating out of 5, one ring per point -->
<wr-radar-chart [axes]="skills" [series]="ratings" [max]="5" />
```

## Polar area

With `variant` set to `polar-area`, each axis gets a wedge per series. The area of a wedge is its value. A missing value is a missing wedge.

```angular-html
<wr-radar-chart variant="polar-area" [axes]="directions" [series]="wind" toggleableLegend />
```

```angular-ts
directions = ['N', 'NE', 'E', 'SE', 'S', 'SW', 'W', 'NW'];

// Hours of wind from each direction. A wedge's area, not its radius, is the value.
wind: WrRadarSeries[] = [
  { label: 'Winter', data: [42, 30, 12, 8, 10, 18, 36, 48] },
  { label: 'Summer', data: [12, 16, 28, 34, 30, 22, 14, 10] },
];
```

## Missing values

A missing value, `null` or a non-finite number, breaks the outline at its axis. The series is drawn open and not filled, so no reading is invented.

```angular-html
<wr-radar-chart [axes]="axes" [series]="survey" [max]="100" />
```

```angular-ts
survey: WrRadarSeries[] = [
  { label: '2025', data: [62, 71, 58, 66, 74] },
  // No Range figure for 2026: the outline breaks there and is not filled.
  { label: '2026', data: [70, 76, null, 72, 79] },
];
```

## Toggle series

`toggleableLegend` makes each legend row a button. A hidden series leaves the drawing, the tooltip and the data table.

```angular-html
<wr-radar-chart [axes]="axes" [series]="teams" [max]="100" toggleableLegend [(hiddenSeries)]="hidden" />
```

```angular-ts
hidden = signal<readonly number[]>([]);
```

## Data table

`dataTable` adds a table only screen readers reach: a row per axis, a column per series shown. Nothing changes on screen.

```angular-html
<wr-radar-chart [axes]="axes" [series]="models" [max]="100" ariaLabel="Two models compared" dataTable />
```

## Accessibility

| Part | Behaviour |
| --- | --- |
| Drawing | One `role="img"`, named by `ariaLabel`. The polygons and wedges announce nothing. |
| Numbers | In the tooltip, which is pointer only, and in the table `dataTable` adds. |
| Series | Each has its own dash as well as its colour, so outlines differ without hue. |
| Axis names | Real text. A long name is cut with an ellipsis; the tooltip and the table carry it whole. |
| Keyboard | No tab stop, unless `toggleableLegend` makes the legend rows buttons. |

## API

| Name | Description | Type | Default |
| --- | --- | --- | --- |
| `axes` | The axes' names, clockwise from twelve o'clock. A series takes one value per axis, in this order. Three at least: with fewer the chart draws the grid and no series. | `readonly string[]` | `[]` |
| `series` | One polygon per series. A series with no `color` takes the next entry from the chart's palette, and each takes the next dash, the first one solid. | `readonly WrRadarSeries[]` | `[]` |
| `variant` | How the series are drawn. `'polygon'` joins each series' values into a polygon, one vertex per axis. `'polar-area'` gives each axis an equal-angle wedge per series whose AREA is the value — the radius grows with the square root of the value, so the ink a wedge paints is proportional to what it stands for — with the series overlaid. The legend, the toggle, the tooltip and the data table are the same in both. | `WrRadarVariant` | `'polygon'` |
| `ariaLabel` | Accessible name of the drawing. The shapes carry no text and the legend has the series names only, so this is where to say what the chart shows — or turn on `dataTable`. Falls back to `radarChart.label`, or to `radarChart.polarAreaLabel` in the polar-area variant, which is also the data table's caption. | `string \| null` | `null` |
| `max` | The value of the outer ring. `0` fits the scale to the series shown, on a readable step and including zero; a value above `0` fixes it, from zero at the centre — a score out of 100, a rating out of 5 — with its rings on a readable step that divides it (see `rings`). A value outside a fixed scale is drawn on its edge, and the tooltip and the data table still give its own figure. | `number` | `0` |
| `rings` | About how many rings the grid draws between the centre and the outer ring, each on a readable step — 1, 2, 2.5 or 5 times a power of ten. A fitted scale aims for this many and rounds its step up onto that ladder. A fixed `max` takes the step that divides it into the count nearest this one, the fewer on a tie, so a rating out of 5 gets a ring per point and a score out of 100 a ring per 25; only a `max` that no such step divides, such as 37, is cut into exactly this many equal rings. Whole numbers from 1 to 10. | `number` | `4` |
| `size` | The drawing's diameter in CSS pixels, at least 120. The axis names sit in a gutter round it, so the chart is wider than this by the gutter on either side; in a narrower container the drawing shrinks to fit. | `number` | `280` |
| `showGrid` | Show the rings, the spokes and the ring values. The axis names stay. | `boolean` | `true` |
| `showLegend` | Show the legend under the chart. | `boolean` | `true` |
| `toggleableLegend` | Make each legend row a toggle button that shows and hides its series, through `hiddenSeries`. A row is a `<button aria-pressed>`, pressed while its series is shown, so the legend becomes one tab stop per series. | `boolean` | `false` |
| `hiddenSeries` | The positions in `series` of the series that are hidden. Positions rather than labels, since two series may share a label. A toggleable legend writes it, and a host may bind it with or without one: `[(hiddenSeries)]`. A hidden series is left out of everything that reads its values: it draws no polygon and no dots, it has no row in the tooltip and no column in the data table, and a fitted scale is fitted to the series still shown. The axes do not change, since they belong to the chart rather than to one series. The legend keeps the hidden series' row, struck through, so it can be shown again; the row says "hidden" to a screen reader as well. A position past the end of `series` is kept and ignored. | `readonly number[]` | `[]` |
| `showDots` | Show a dot at every value: on the polygon's vertex, or in the polar-area variant on the middle of the wedge's arc, where the value reads against the rings. | `boolean` | `true` |
| `showArea` | Fill each closed polygon with its colour, faintly (`--wr-radar-chart-area-opacity`), under every outline — the name the line chart and the sparkline give the same fill. A series with a missing value is never filled, whatever this says: its outline is open. In the polar-area variant every wedge is filled, since the outline round them always closes, and a missing value is a missing wedge. | `boolean` | `true` |
| `tooltip` | Show a tooltip for the axis nearest the pointer: its name, and every series' value on it; an axis no series shown has a value on opens none. Pointer only — the data table is where the same numbers are for a keyboard or a screen reader. | `boolean` | `true` |
| `valueFormat` | Writes every number the chart shows: the ring values, the tooltip and the data table. `null` uses `Intl.NumberFormat` in `LOCALE_ID`, with compact ring values (`1.2K`) unless the full numbers are shorter. | `((value: number) => string) \| null` | `null` |
| `dataTable` | Render the chart's figures as a table that only assistive technology reaches: a row per axis, headed by its name, and a column per series shown, every value written the way the tooltip writes it. A missing value is an empty cell. The drawing is one named `role="img"`, which hides everything inside it, so without the table the numbers are nowhere a screen reader can walk. It is rendered beside the drawing, clipped to nothing: it takes no room, draws nothing and holds no tab stop. A hidden series leaves it. | `boolean` | `false` |

## Types

```angular-ts
interface WrRadarSeries {
  label: string;
  data: readonly (number | null)[];
  color?: string;
}

type WrRadarVariant = 'polygon' | 'polar-area';
```

| Name | Description | Type | Default |
| --- | --- | --- | --- |
| `WrRadarSeries` | One polygon. | `interface` | — |
| `label`required | Legend, tooltip and table name. | `string` | — |
| `data`required | One value per axis, in the order of `axes`. `null`, a non-finite or an absent value is missing. | `readonly (number \| null)[]` | — |
| `color` | CSS colour for the outline and fill. | `string` | `palette` |
| `WrRadarVariant` | How the series are drawn: polygons, or wedges whose area is the value. | `'polygon' \| 'polar-area'` | — |

## CSS variables

Set these on the component's selector or a wrapper, not on `:root`: the defaults are declared on `ngwr/charts/radar-chart`'s own element.

| Variable | Default | Declared on |
| --- | --- | --- |
| `--wr-radar-chart-area-opacity` | `0.15` | `.wr-radar-chart` |
| `--wr-radar-chart-color` | `var(--wr-color-on-surface)` | `.wr-radar-chart` |
| `--wr-radar-chart-crosshair-color` | `var(--wr-color-on-surface-muted)` | `.wr-radar-chart` |
| `--wr-radar-chart-dot-size` | `6px` | `.wr-radar-chart` |
| `--wr-radar-chart-font-family` | `var(--wr-font-family-base)` | `.wr-radar-chart` |
| `--wr-radar-chart-gap` | `var(--wr-space-lg)` | `.wr-radar-chart` |
| `--wr-radar-chart-grid-color` | `color-mix(in srgb, var(--wr-border-base) 70%, transparent)` | `.wr-radar-chart` |
| `--wr-radar-chart-grid-width` | `1px` | `.wr-radar-chart` |
| `--wr-radar-chart-gutter-x` | `5rem` | `.wr-radar-chart` |
| `--wr-radar-chart-gutter-y` | `calc(var(--wr-radar-chart-label-line-height) + var(--wr-radar-chart-label-gap))` | `.wr-radar-chart` |
| `--wr-radar-chart-hover-center` | `var(--wr-color-surface)` | `.wr-radar-chart` |
| `--wr-radar-chart-label-color` | `var(--wr-color-on-surface)` | `.wr-radar-chart` |
| `--wr-radar-chart-label-font-size` | `var(--wr-text-xs)` | `.wr-radar-chart` |
| `--wr-radar-chart-label-gap` | `var(--wr-space-sm)` | `.wr-radar-chart` |
| `--wr-radar-chart-label-line-height` | `var(--wr-text-xs-leading)` | `.wr-radar-chart` |
| `--wr-radar-chart-label-max-width` | `10rem` | `.wr-radar-chart` |
| `--wr-radar-chart-line-width` | `2px` | `.wr-radar-chart` |
| `--wr-radar-chart-ring-label-color` | `var(--wr-color-on-surface-muted)` | `.wr-radar-chart` |
| `--wr-radar-chart-ring-label-halo` | `var(--wr-color-surface)` | `.wr-radar-chart` |
| `--wr-radar-chart-ring-label-offset` | `var(--wr-space-sm)` | `.wr-radar-chart` |

## Dependencies

| Built on | [Chart Legend](https://ngwr.dev/charts/chart-legend), [Popover](https://ngwr.dev/reference/components/popover) |
| --- | --- |

## See also

- [Line Chart](https://ngwr.dev/charts/line-chart) — One or more series of values as lines or as an area chart, overlaid or stacked.
- [Bar Chart](https://ngwr.dev/charts/bar-chart) — Bars for one or several series, grouped or stacked, standing up or lying along a row, with lines over them.
- [Donut Chart](https://ngwr.dev/charts/donut-chart) — Parts of a whole as a ring or a pie.
- [Colors](https://ngwr.dev/guides/tokens/colors) — The --wr-color-* tokens, and which one to use for fills, text and borders.
- [Chart Legend](https://ngwr.dev/charts/chart-legend) — A chart's key: a swatch, a name and a value per series.
- [Popover](https://ngwr.dev/reference/components/popover) — Show a template, or a text tooltip, next to its trigger.
