RadarChart
Values on radial axes, one polygon per series, over a polygon or circle grid.
Default
One series as a filled polygon over a polygon grid.
Showing total visitors for the last 6 months
| Month | Desktop |
|---|---|
| January | 186 |
| February | 305 |
| March | 237 |
| April | 73 |
| May | 209 |
| June | 214 |
Code
<RadarChart data={rows} config={{ desktop: { label: "Desktop", color: "var(--chart-1)" } }}
x="month" tooltip={{ cursor: false }} />Usage
import { RadarChart } from "@elements/ui/chart-radar";
import type { ChartConfig } from "@elements/ui/chart";
<RadarChart data={rows} {config} x="month" />
<RadarChart data={rows} {config} x="month" grid={{ type: "circle" }} dots legend />Examples
Dots
A dot on every vertex.
Showing total visitors for the last 6 months
| Month | Desktop |
|---|---|
| January | 186 |
| February | 305 |
| March | 237 |
| April | 73 |
| May | 209 |
| June | 214 |
Code
<RadarChart data={rows} config={{ desktop }} x="month" dots={{ r: 4 }} tooltip={{ cursor: false }} />Lines only
lines strokes each polygon; fillOpacity 0 leaves it hollow.
Showing total visitors for the last 6 months
| Month | Desktop | Mobile |
|---|---|---|
| January | 186 | 80 |
| February | 305 | 200 |
| March | 237 | 120 |
| April | 73 | 190 |
| May | 209 | 130 |
| June | 214 | 140 |
Code
<RadarChart data={rows} {config} x="month" lines fillOpacity={0}
grid={{ radialLines: false }} tooltip={{ indicator: "line", cursor: false }} />Custom label
angleAxis detail puts both values over each month.
Showing total visitors for the last 6 months
| Month | Desktop | Mobile |
|---|---|---|
| January | 186 | 80 |
| February | 305 | 200 |
| March | 237 | 120 |
| April | 73 | 190 |
| May | 209 | 130 |
| June | 214 | 140 |
Code
<RadarChart data={rows} {config} x="month" margin={{ top: 10, right: 10, bottom: 10, left: 10 }}
angleAxis={{ detail: (row) => `${row.desktop}/${row.mobile}` }}
tooltip={{ indicator: "line", cursor: false }} />Grid custom
One ring at a fixed radius and no spokes.
Showing total visitors for the last 6 months
| Month | Desktop |
|---|---|
| January | 186 |
| February | 305 |
| March | 237 |
| April | 73 |
| May | 209 |
| June | 214 |
Code
<RadarChart data={rows} config={{ desktop }} x="month"
grid={{ radialLines: false, radii: [90] }} tooltip={{ hideLabel: true, cursor: false }} />Grid none
grid=false.
Showing total visitors for the last 6 months
| Month | Desktop |
|---|---|
| January | 186 |
| February | 305 |
| March | 237 |
| April | 73 |
| May | 209 |
| June | 214 |
Code
<RadarChart data={rows} config={{ desktop }} x="month" grid={false} dots={{ r: 4 }} />Grid circle
grid type=circle.
Showing total visitors for the last 6 months
| Month | Desktop |
|---|---|
| January | 186 |
| February | 305 |
| March | 237 |
| April | 73 |
| May | 209 |
| June | 214 |
Code
<RadarChart data={rows} config={{ desktop }} x="month" grid={{ type: "circle" }} dots={{ r: 4 }} />Grid circle, no lines
Circles without spokes.
Showing total visitors for the last 6 months
| Month | Desktop |
|---|---|
| January | 186 |
| February | 305 |
| March | 237 |
| April | 73 |
| May | 209 |
| June | 214 |
Code
<RadarChart data={rows} config={{ desktop }} x="month"
grid={{ type: "circle", radialLines: false }} dots={{ r: 4 }} />Grid circle filled
Circles washed in the series color.
Showing total visitors for the last 6 months
| Month | Desktop |
|---|---|
| January | 186 |
| February | 305 |
| March | 237 |
| April | 73 |
| May | 209 |
| June | 214 |
Code
<RadarChart data={rows} config={{ desktop }} x="month"
grid={{ type: "circle", fill: true }} fillOpacity={0.5} />Grid filled
Polygons washed in the series color.
Showing total visitors for the last 6 months
| Month | Desktop |
|---|---|
| January | 186 |
| February | 305 |
| March | 237 |
| April | 73 |
| May | 209 |
| June | 214 |
Code
<RadarChart data={rows} config={{ desktop }} x="month" grid={{ fill: true }} fillOpacity={0.5} />Multiple
Every series in the config, one polygon each.
Showing total visitors for the last 6 months
| Month | Desktop | Mobile |
|---|---|---|
| January | 186 | 80 |
| February | 305 | 200 |
| March | 237 | 120 |
| April | 73 | 190 |
| May | 209 | 130 |
| June | 214 | 140 |
Code
<RadarChart data={rows} {config} x="month" tooltip={{ indicator: "line", cursor: false }} />Legend
A legend under the plot.
Showing total visitors for the last 6 months
- Desktop
- Mobile
| Month | Desktop | Mobile |
|---|---|---|
| January | 186 | 80 |
| February | 305 | 200 |
| March | 237 | 120 |
| April | 73 | 190 |
| May | 209 | 130 |
| June | 214 | 140 |
Code
<RadarChart data={rows} {config} x="month" legend tooltip={{ indicator: "line", cursor: false }} />Icons
Config icons in the legend and tooltip.
Showing total visitors for the last 6 months
- Desktop
- Mobile
| Month | Desktop | Mobile |
|---|---|---|
| January | 186 | 80 |
| February | 305 | 200 |
| March | 237 | 120 |
| April | 73 | 190 |
| May | 209 | 130 |
| June | 214 | 140 |
Code
<RadarChart data={rows} config={{ desktop: { ..., icon: "monitor" }, mobile: { ..., icon: "smartphone" } }}
x="month" legend tooltip={{ indicator: "line", cursor: false }} />Radius axis
Value ticks along one spoke; no category labels.
Showing total visitors for the last 6 months
| Month | Desktop | Mobile |
|---|---|---|
| January | 186 | 80 |
| February | 305 | 200 |
| March | 237 | 120 |
| April | 73 | 190 |
| May | 209 | 130 |
| June | 214 | 140 |
Code
<RadarChart data={rows} {config} x="month" angleAxis={false}
radiusAxis={{ angle: 60, orientation: "middle" }} tooltip={{ indicator: "line", labelKey: "month" }} />Labels
The value at each vertex, outside the polygon.
| Month | Desktop |
|---|---|
| January | 186 |
| February | 305 |
| March | 237 |
| April | 73 |
| May | 209 |
| June | 214 |
Code
<!-- each value just outside its vertex -->
<RadarChart data={rows} {config} x="month" series={["desktop"]} labels dots />Missing values
A month with no value breaks the polygon; connectNulls closes it over that spoke.
| Month | Desktop |
|---|---|
| January | 186 |
| February | 305 |
| March | |
| April | 73 |
| May | 209 |
| June | 214 |
| Month | Desktop |
|---|---|
| January | 186 |
| February | 305 |
| March | |
| April | 73 |
| May | 209 |
| June | 214 |
Code
<!-- March has no value: the polygon breaks there, or connectNulls closes it over the spoke -->
<RadarChart data={gaps} {config} x="month" series={["desktop"]} lines />
<RadarChart data={gaps} {config} x="month" series={["desktop"]} lines connectNulls />Range
A low and a high value per month fill the band between two polygons.
| Month | Range |
|---|---|
| January | 62 – 186 |
| February | 140 – 305 |
| March | 110 – 237 |
| April | 40 – 173 |
| May | 90 – 209 |
| June | 120 – 214 |
Code
<!-- a [low, high] pair per month draws the band between them -->
const ranges = [{ month: "January", temperature: [12, 24] }, ...];
<RadarChart data={ranges} {config} x="month" />Radius and angle axis options
radiusAxis ticks fixes the tick values and the grid rings; allowDecimals false keeps nice ticks whole; reversed puts the largest value at the center. angleAxis reversed runs the spokes counter-clockwise.
| Month | Desktop |
|---|---|
| January | 186 |
| February | 305 |
| March | 237 |
| April | 73 |
| May | 209 |
| June | 214 |
| Skill | Desktop |
|---|---|
| Speed | 3 |
| Range | 2 |
| Power | 1 |
| Focus | 3 |
| Grip | 2 |
| Month | Desktop |
|---|---|
| January | 186 |
| February | 305 |
| March | 237 |
| April | 73 |
| May | 209 |
| June | 214 |
Code
<!-- ticks fixes the values; the grid rings follow them -->
<RadarChart data={rows} {config} x="month" radiusAxis={{ angle: 0, ticks: [100, 250] }} />
<!-- allowDecimals false keeps the ticks on whole numbers -->
<RadarChart data={scores} {config} x="skill" radiusAxis={{ angle: 0, allowDecimals: false }} />
<!-- reversed: the largest value at the center; the spokes run counter-clockwise -->
<RadarChart data={rows} {config} x="month" radiusAxis={{ angle: 0, reversed: true }} angleAxis={{ reversed: true }} />Center and margin
cx and cy place the center as px or a percentage of the plot inside the margin; the grid and axes follow it.
| Month | Desktop | Mobile |
|---|---|---|
| January | 186 | 80 |
| February | 305 | 200 |
| March | 237 | 120 |
| April | 73 | 190 |
| May | 209 | 130 |
| June | 214 | 140 |
Code
<RadarChart data={rows} {config} x="month"
margin={{ left: 40 }} cx="40%" cy="60%" />Animation timing
animation sets when the marks start moving, how long they take and their easing: a CSS easing name, a cubic-bezier, spring, or a function of progress.
| Month | Desktop | Mobile |
|---|---|---|
| January | 186 | 80 |
| February | 305 | 200 |
| March | 237 | 120 |
| April | 73 | 190 |
| May | 209 | 130 |
| June | 214 | 140 |
Code
<!-- wait 150ms, then take 900ms to enter or move to new data -->
<RadarChart data={rows} {config} x="month"
animation={{ begin: 150, duration: 900, easing: (t) => t * t }} />Legend and tooltip types
legendType on a config entry sets that series' legend icon, and none leaves a drawn series out of the legend; tooltipType none leaves it out of the tooltip.
- Desktop
- Mobile
| Month | Desktop | Mobile | Other |
|---|---|---|---|
| January | 186 | 80 | 45 |
| February | 305 | 200 | 100 |
| March | 237 | 120 | 150 |
| April | 73 | 190 | 50 |
| May | 209 | 130 | 100 |
| June | 214 | 140 | 160 |
Code
<!-- desktop's legend icon is a line; mobile is left out of the tooltip, other out of the legend -->
<RadarChart data={rows} x="month" legend config={{
desktop: { label: "Desktop", color: "var(--chart-1)", legendType: "line" },
mobile: { label: "Mobile", color: "var(--chart-2)", tooltipType: "none" },
other: { label: "Other", color: "var(--chart-3)", legendType: "none" },
}} />Toggles, keyboard and table
Tab to the chart, arrows move around the spokes; the legend hides series; the table shows the data. The radius axis is fixed at 0 to 400 with three ticks toward three o'clock.
| Month | Desktop | Mobile |
|---|---|---|
| January | 186 | 80 |
| February | 305 | 200 |
| March | 237 | 120 |
| April | 73 | 190 |
| May | 209 | 130 |
| June | 214 | 140 |
Code
<RadarChart data={rows} {config} x="month" legend={{ toggle: true }} hidden={state.hidden}
radiusAxis={{ angle: 0, tickCount: 3, domain: [0, 400], tickFormatter: (v) => `${v}+` }}
active={state.active} onActiveChange={() => state.changes++}
onItemClick={(i) => state.clicked = i} />Polar axes
innerRadius starts the value scale and the rings away from the center; polarAngles places the spokes; the axes draw lines, tick marks and titles; a second radius or angle axis gives a series its own scale or spoke order.
| Month | Desktop |
|---|---|
| January | 186 |
| February | 305 |
| March | 237 |
| April | 73 |
| May | 209 |
| June | 214 |
| Month | Desktop |
|---|---|
| January | 186 |
| February | 305 |
| March | 237 |
| April | 73 |
| May | 209 |
| June | 214 |
| Month | Desktop | Mobile |
|---|---|---|
| January | 186 | 80 |
| February | 305 | 200 |
| March | 237 | 120 |
| April | 73 | 190 |
| May | 209 | 130 |
| June | 214 | 140 |
| Month | Desktop | Mobile |
|---|---|---|
| January | 186 | 80 |
| February | 305 | 200 |
| March | 237 | 120 |
| April | 73 | 190 |
| May | 209 | 130 |
| June | 214 | 140 |
Code
<RadarChart data={rows} config={{ desktop }} x="month" innerRadius={30} />
<RadarChart data={rows} config={{ desktop }} x="month"
grid={{ polarAngles: [90, 0, 270, 180] }}
angleAxis={{ axisLine: true, axisLineType: "circle", tickLine: true, label: "Visits" }}
radiusAxis={{ angle: 30, axisLine: true, tickLine: true, label: "Count" }} />
<!-- two radius axes: mobile has a scale of its own -->
<RadarChart data={rows} {config} x="month"
radiusAxis={[{ angle: 90 }, { angle: 270, series: ["mobile"], domain: [0, 1000] }]} />
<!-- two angle axes: mobile runs its spokes the other way -->
<RadarChart data={rows} {config} x="month"
angleAxis={[{}, { series: ["mobile"], reversed: true, hide: true }]} />Grid style
grid stroke, strokeDasharray and strokeWidth restyle the rings and spokes.
| Month | Desktop |
|---|---|
| January | 186 |
| February | 305 |
| March | 237 |
| April | 73 |
| May | 209 |
| June | 214 |
Code
<!-- the rings and spokes in the first chart color, dashed, 2px -->
<RadarChart data={rows} {config} x="month"
grid={{ stroke: "var(--chart-1)", strokeDasharray: "3 3", strokeWidth: 2 }} />Radius axis options
unit follows each value in the tooltip; orientation sets the ticks beside their spoke; allowDataOverflow keeps a domain the data runs past; includeHidden keeps a hidden series in the scale; angleAxis angle turns the category labels.
| Month | Desktop |
|---|---|
| January | 186 |
| February | 305 |
| March | 237 |
| April | 73 |
| May | 209 |
| June | 214 |
| Month | Desktop |
|---|---|
| January | 186 |
| February | 305 |
| March | 237 |
| April | 73 |
| May | 209 |
| June | 214 |
| Month | Desktop |
|---|---|
| January | 186 |
| February | 305 |
| March | 237 |
| April | 73 |
| May | 209 |
| June | 214 |
| Month | Desktop | Mobile |
|---|---|---|
| January | 186 | 80 |
| February | 305 | 200 |
| March | 237 | 120 |
| April | 73 | 190 |
| May | 209 | 130 |
| June | 214 | 140 |
| Month | Desktop |
|---|---|
| January | 186 |
| February | 305 |
| March | 237 |
| April | 73 |
| May | 209 |
| June | 214 |
Code
<!-- unit follows each value in the tooltip -->
<RadarChart data={rows} {config} x="month" radiusAxis={{ angle: 0, unit: "k" }} />
<!-- the ticks beside the spoke, ending at their value -->
<RadarChart data={rows} {config} x="month" radiusAxis={{ angle: 90, orientation: "left" }} />
<!-- keep 0 to 200 though February reaches 305 -->
<RadarChart data={rows} {config} x="month" radiusAxis={{ angle: 0, domain: [0, 200], allowDataOverflow: true }} />
<!-- hiding a series keeps the scale -->
<RadarChart data={rows} {config} x="month" legend={{ toggle: true }}
radiusAxis={{ angle: 0, includeHidden: true }} />
<!-- each month label turned 45 degrees -->
<RadarChart data={rows} {config} x="month" angleAxis={{ angle: 45 }} />Radius scale
niceTicks none ends the radius axis at the data; scale picks a square root or log scale; type category gives each distinct value a ring of its own; range sets the radii the axis spans.
| Month | Desktop |
|---|---|
| January | 186 |
| February | 305 |
| March | 237 |
| April | 73 |
| May | 209 |
| June | 214 |
| Month | Desktop |
|---|---|
| January | 186 |
| February | 305 |
| March | 237 |
| April | 73 |
| May | 209 |
| June | 214 |
| Month | Desktop |
|---|---|
| January | 186 |
| February | 305 |
| March | 237 |
| April | 73 |
| May | 209 |
| June | 214 |
| Month | Desktop |
|---|---|
| January | 186 |
| February | 305 |
| March | 237 |
| April | 73 |
| May | 209 |
| June | 214 |
Code
<!-- the axis ends at the data's own maximum, ticks evenly spaced -->
<RadarChart data={rows} {config} x="month" radiusAxis={{ angle: 0, niceTicks: "none" }} />
<!-- a square root scale: small values spread out -->
<RadarChart data={rows} {config} x="month" radiusAxis={{ angle: 0, scale: "sqrt" }} />
<!-- each distinct value on a ring of its own, in data order -->
<RadarChart data={rows} {config} x="month" radiusAxis={{ angle: 0, type: "category" }} />
<!-- the axis spans 20 to 60px from the center -->
<RadarChart data={rows} {config} x="month" radiusAxis={{ angle: 0, range: [20, 60] }} />Radial layout
layout radial gives each category a ring from the center out and each value a share of the turn, the value ticks round the rim.
| Month | Desktop |
|---|---|
| January | 186 |
| February | 305 |
| March | 237 |
| April | 73 |
| May | 209 |
| June | 214 |
Code
<!-- a ring per month from the center out, each value a share of the turn from twelve o'clock -->
<RadarChart data={rows} {config} x="month" layout="radial" radiusAxis dots />Moving to new data
animation matchBy pairs old and new items by a key, so each month slides to its new place; interpolate draws every frame with a function of your own, here one that starts each point after the one before.
| Month | Desktop |
|---|---|
| January | 186 |
| February | 305 |
| March | 237 |
| April | 73 |
| May | 209 |
| June | 214 |
| Month | Desktop |
|---|---|
| January | 186 |
| February | 305 |
| March | 237 |
| April | 73 |
| May | 209 |
| June | 214 |
Code
<!-- each month keeps its point: the window slides instead of every point changing value -->
<RadarChart data={rows} {config} x="month" animation={{ matchBy: matchByDataKey("month") }} />
<!-- (items, t) => the items to draw: each matched item from prev to next, started one after another -->
<RadarChart data={rows} {config} x="month" animation={{ interpolate: stagger }} />