# Radar chart

> Compares one or more series across 3 to 12 categories on a spider web, for skills, product scores, survey results and plan comparisons.

- Type: React component (Charts & Stats)
- Access: Pro (the source needs a Wingo UI Pro plan, see https://wingo-ui.com/pricing)
- Version: 1.0.0
- Install: `npx wingo-ui@latest add radar-chart`
- Docs: https://wingo-ui.com/components/radar-chart

## Interaction

Each series grows out of the center the first time the chart scrolls into view, the series a beat apart. Move the mouse around the web and the nearest spoke lights up, its label turns bold, the dots on it swell and a readout lists every visible series for that category. On a phone, tap near a spoke to pin the readout, drag around to move from spoke to spoke (a vertical drag still scrolls the page), tap the same spoke again or anywhere outside to clear it. With the keyboard, Tab to the chart: Right / Down move clockwise, Left / Up counter-clockwise (both wrap around), Home / End jump to the first and last axis and Escape clears; a live region reads each axis. Click or tap a legend entry to hide its series, hover or focus one to highlight it. Long category names wrap onto two lines, then shorten with an ellipsis on narrow screens; the full name stays in the readout and the screen reader table.

## Installation

```bash
npx wingo-ui@latest add radar-chart
```

Pro item: run `npx wingo-ui@latest login` once with a Pro account. The CLI adds the files, their dependencies and a version record for updates.

With shadcn: `npx shadcn@latest add @wingo-ui/radar-chart` (needs the @wingo-ui registry with your API key in components.json)

Files:

- `components/ui/radar-chart.tsx`

npm dependencies: `npm i motion d3-shape`

Wingo UI dependencies (installed automatically):

- [Chart kit](https://wingo-ui.com/components/chart-kit) ([Markdown](https://wingo-ui.com/components/chart-kit.md))
- [UIProvider](https://wingo-ui.com/components/ui-config) ([Markdown](https://wingo-ui.com/components/ui-config.md))
- [useLocale](https://wingo-ui.com/components/use-locale) ([Markdown](https://wingo-ui.com/components/use-locale.md))

## Usage

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

const data = [
  { label: "Speed", starter: 6, pro: 9 },
  { label: "Storage", starter: 4, pro: 8 },
  { label: "Integrations", starter: 5, pro: 9 },
  { label: "Support", starter: 3, pro: 8 },
  { label: "Security", starter: 6, pro: 9 },
  { label: "Analytics", starter: 4, pro: 7 },
]

export function PlanComparison() {
  return (
    <RadarChart
      data={data}
      series={[
        { key: "starter", label: "Starter" },
        { key: "pro", label: "Pro" },
      ]}
      max={10}
      label="Starter vs. Pro, scored out of 10"
    />
  )
}
```

## Props

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `data` | `ChartDatum[]` |  | One row per axis, in clockwise order from the top: { label: "Speed", starter: 6, pro: 9 }. A missing value sits at the center. |
| `xKey?` | `string` | `"label"` | The row key that names each axis. |
| `series?` | `RadarChartSeries[]` |  | Which keys to draw, in color order: { key, label?, color?, name?, dashed? }. dashed draws an outline only (a target or last period) with a muted tooltip row. Inferred from the numeric keys of the first rows when omitted. |
| `colors?` | `string[]` |  | Per-position palette overrides: a slot ("series-3"), a tone ("neutral", "brand") or any CSS color. |
| `size?` | `"sm" \| "md" \| "lg"` | `"md"` | The largest square the chart takes: 240, 320 or 420px. It shrinks to the container's width below that. |
| `shape?` | `"polygon" \| "circle"` | `"polygon"` | The grid rings: straight-edged polygons or circles. |
| `levels?` | `number` | `4` | How many grid rings divide the range from min to max. |
| `max?` | `number` | `0` | The value on the outer ring (100 for percentages). 0, or anything not above min, rounds the largest visible value up so every ring lands on a round number. |
| `min?` | `number` | `0` | The value at the center. |
| `fillOpacity?` | `number` | `0.18` | Opacity of each series' fill (dashed series have no fill). |
| `strokeWidth?` | `number` | `2` | Outline width in px. |
| `curve?` | `"linear" \| "cardinal"` | `"linear"` | Straight edges between axes, or a smooth closed curve through every point. |
| `showDots?` | `boolean` | `true` | A dot on every value. Without them the inspected axis still shows its dots. |
| `showGrid?` | `boolean` | `true` | The rings and spokes behind the series. |
| `showAxisLabels?` | `boolean` | `true` | Category names around the web. Off, the web takes the whole square. |
| `showLevelLabels?` | `boolean` | `false` | The value of each ring, printed along the top spoke. |
| `showLegend?` | `boolean` | `true` | A legend for two or more series. |
| `legendPosition?` | `"top" \| "bottom"` | `"bottom"` | Where the legend sits; it wraps onto more lines on narrow screens. |
| `legendToggle?` | `boolean` | `true` | Legend entries are toggle buttons that hide and show a series (the last visible one stays). |
| `showTooltip?` | `boolean` | `true` | The readout for the inspected axis. Off, the spoke still highlights and the live region still speaks. |
| `tooltipMode?` | `"auto" \| "float" \| "fixed"` | `"auto"` | float beside the spoke's end (mouse), fixed above the chart where a finger cannot cover it (touch); auto picks by pointer. |
| `valueFormat?` | `ChartValueFormat` | `"number"` | How values print in the readout, ring labels and table: number, compact, currency or percent. Percent takes whole numbers (82 -> "82%"). |
| `currency?` | `string` | `"USD"` | ISO 4217 code for valueFormat currency. |
| `decimals?` | `number` | `""` | Fraction digits in the readout and table; auto by magnitude when unset (Default in the playground). |
| `formatValue?` | `(value: number, context: { series: string; kind: "tooltip" \| "level" \| "table" }) => string` |  | Replaces the built-in value formatting everywhere. |
| `locale?` | `string` | `""` | Locale for numbers. Empty uses the UIProvider / LocaleProvider locale (en-US in the playground). |
| `animated?` | `boolean` | `true` | Series grow out of the center on first view, morph when the data changes and fade when hidden or highlighted. Always off under reduced motion. |
| `loading?` | `boolean` | `false` | A round skeleton in the chart's square while data loads. |
| `emptyState?` | `ReactNode` |  | Replaces the built-in empty state when no row has a value. |
| `label?` | `string` | `""` | The accessible name of the chart and the table caption. Empty joins the series names. |
| `description?` | `string` | `""` | A sentence for screen readers that states the takeaway. |
| `surface?` | `string` | `""` | The color behind the chart, used to ring the dots and halo the ring labels. Empty uses the surface token. |
| `hiddenSeries?` | `string[]` |  | Hidden series keys when you control legend toggling; pair with onHiddenSeriesChange. |
| `defaultHiddenSeries?` | `string[]` |  | Series hidden at first, uncontrolled. |
| `onHiddenSeriesChange?` | `(keys: string[]) => void` |  | Called when a legend toggle hides or shows a series. |
| `activeIndex?` | `number \| null` |  | The inspected axis when you control it. |
| `defaultActiveIndex?` | `number \| null` | `""` | The axis inspected at first, uncontrolled. Unset (Default in the playground) starts with no readout. |
| `onActiveIndexChange?` | `(index: number \| null) => void` |  | Called as the inspected axis changes (mouse, touch or keyboard) and with null when it clears. |
| `labels?` | `Partial<RadarChartLabels>` |  | Strings: empty, loading, table, inspectHint, showSeries, hideSeries, axis (Category), compare ((comparison)). |
| `classNames?` | `Partial<Record<RadarChartSlot, string>>` |  | Classes for legend, plot, tooltip, table, grid, axisLabel, levelLabel, area, dot and inspect. |

## Parts

### DEFAULT_RADAR_CHART_LABELS (constant)

The English strings the chart uses, the chart kit's labels plus axis and compare. Spread it to translate a few.

### RadarChartSeries (type)

One series: { key, label?, color?, name?, dashed? }.

### RadarChartLabels (type)

The shape of the labels prop.

### RadarChartFormatContext (type)

What formatValue receives besides the value: the series key and where it prints ("tooltip", "level" or "table").

## Examples

- **Skills against a bar**: A neutral series over a dashed target, circle grid, cardinal curve and ring labels.
- **Single series**: One brand-colored series on a circle grid; no legend for one series.
- **Three series, toggled legend**: hiddenSeries controlled from the legend, which sits on top.
- **Percent**: valueFormat percent with max 100; a long category name wraps onto two lines.
- **Loading and empty**: The round skeleton and the empty state in the chart's square.

## See also

- [Line chart](https://wingo-ui.com/components/line-chart) ([Markdown](https://wingo-ui.com/components/line-chart.md))
- [Bar chart](https://wingo-ui.com/components/bar-chart) ([Markdown](https://wingo-ui.com/components/bar-chart.md))
- [Donut chart](https://wingo-ui.com/components/donut-chart) ([Markdown](https://wingo-ui.com/components/donut-chart.md))
- [Radial bar](https://wingo-ui.com/components/radial-bar) ([Markdown](https://wingo-ui.com/components/radial-bar.md))
- [Stat Card](https://wingo-ui.com/components/stat-card) ([Markdown](https://wingo-ui.com/components/stat-card.md))

---

Canonical: https://wingo-ui.com/components/radar-chart
More components: https://wingo-ui.com/components · Index for agents: https://wingo-ui.com/llms.txt
