# Radar chart

One or more series across several axes, drawn as polygons of dither cells whose density steps up ring by ring.

> For the complete documentation index, see [llms.txt](/llms.txt). Markdown variants are available by appending `.md` to any URL or sending an `Accept: text/markdown` header. The dithercn agent skill, for building any dither on the engine, is at [/.well-known/agent-skills/dithercn/SKILL.md](/.well-known/agent-skills/dithercn/SKILL.md).

<ComponentPreview src="examples/radar-chart-demo.tsx" size="lg" controls="radarChartControls">
  <RadarChartDemo />
</ComponentPreview>

## Installation [#installation]

<InstallBlock name="radar-chart" />

## Usage [#usage]

```tsx
import { RadarChart } from "@/components/dithercn/radar-chart";

export function Evals() {
  return (
    <RadarChart
      axes={["Reasoning", "Coding", "Math", "Writing", "Vision"]}
      series={[
        { label: "Model v3", values: [86, 91, 78, 72, 64] },
        { label: "Model v2", values: [71, 74, 69, 76, 40] },
      ]}
      max={100}
    />
  );
}
```

Axes run clockwise from 12 o'clock. Each series lists one value per axis in the same order. Without `max`, the outer ring sits at a round number above the largest value.

Every series is a polygon of whole dither cells with a solid one-cell outline and square markers on its corners. With `fill="gradient"` the density steps up once per ring, thin at the centre and dense near the rim, so the grid reads straight through the shape. Each series takes the next palette colour. Where series overlap their cells interleave, so neither hides the other, and every outline stays on top.

Move the pointer around the chart and the readout snaps to the nearest axis, with every series' value there. Focus the chart and the arrow keys step around the axes. Hover a legend entry to spotlight a series, click to keep it lit, and press Escape to let go.

The chart fills its container up to `size` and shrinks with it, keeping room for the labels.

## Examples [#examples]

### Single series in a card [#single-series-in-a-card]

One series in `green` with `fill="dotted"` and a round grid. The legend hides itself when there is only one series.

<ComponentPreview src="examples/radar-chart-card.tsx">
  <RadarChartCard />
</ComponentPreview>

### Comparing plans [#comparing-plans]

Three series on seven axes with `fill="hatched"`, five rings and `bloom="high"`. Hatching keeps overlapping shapes readable because each one's lines run between the other's.

<ComponentPreview src="examples/radar-chart-compare.tsx" size="lg">
  <RadarChartCompare />
</ComponentPreview>

## Props [#props]

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `axes` (required) | `[string, ...string[]]` |  | Axis labels, clockwise from the top. Three or more read best. |
| `series` (required) | `[RadarSeries, ...RadarSeries[]]` |  | { label: string; values: number[]; color?: DitherColor; fill?: FillVariant }, one value per axis. |
| `max` | `number` | `A round number above the largest value` | The value at the outer ring. |
| `rings` | `number` | `4` | Grid rings. They also set the steps of the gradient fill. |
| `grid` | `"polygon" \| "circle"` | `"polygon"` | Shape of the grid rings. |
| `fill` | `"gradient" \| "dotted" \| "hatched" \| "solid"` | `"gradient"` | Texture of every series. A series' own fill wins. |
| `bloom` | `"off" \| "low" \| "high"` | `"off"` | Soft glow in each series' colour behind it. |
| `colors` | `DitherColor[]` |  | Colours by series position. A series' own color wins. |
| `size` | `number` | `360` | Largest width and height in CSS pixels. It shrinks to fit its container. |
| `format` | `Intl.NumberFormatOptions \| ((value: number) => string)` | `Compact, as in 1.2K` | How values are written in the readout and the data table. |
| `legend` | `boolean` | `With two or more series` | Show the legend. |
| `interactive` | `boolean` | `true` | The axis scrub, keyboard and legend spotlight. false draws a static image. |
| `animate` | `boolean` | `true` | Grow out from the centre the first time the chart is seen. |
| `matrix` | `"bayer2" \| "bayer4" \| "bayer8" \| "blue-noise"` | `"bayer4"` | Threshold pattern of the gradient fill. |
| `cell` | `number` | `--dither-cell` | Size of one dither cell in CSS pixels. |

## Notes [#notes]

* The chart is a focusable group with a summary label. The arrow keys move between axes, a live region reads each axis's values, and a hidden table lists every value.
* The shapes grow out from the centre once when the chart scrolls into view. With reduced motion they appear at once and the readout moves without easing.
* The drawing is one SVG path per series, built from whole cells snapped to device pixels. Scrubbing only moves the readout by transform and restyles one spoke.