RadarChart

Several comparable measures as one closed polygon per profile, for comparing shapes across five to eight axes. Every axis shares one radial scale, so the measures have to be normalized to a common range first.

vue
<UiRadarChart :data="..." :categoryKey="..." :series="..." :ariaLabel="..." />

Needs the charts module

This component ships in @jgastager/bundy-ui/charts, a separate module so projects that never draw a chart don't carry the paint classes these need. Nothing extra to install — just add the module entry. See Charts.


Options

One block per prop — what it does, and what it looks like set.

Data

required

data is one object per axis with one field per profile. Every axis shares a single radial scale, so the fields have to be commensurable — scores out of 100, percentages, ratings. Mixing a count with a percentage on the same radar produces a shape that means nothing.

  • Alice
  • Bob

Every axis shares one radial scale, so the fields have to be comparable quantities. Normalize to a common range first if they aren't, or the shape is meaningless.

There's no animate prop. The marks are plain SVG elements Vue patches directly, so a data change re-renders rather than tweening; what motion there is comes from CSS transitions on hover, which this chart doesn't have.

Category key

required

categoryKey sets which field on each row names its axis.

Series

required

series are the profiles to draw, as field names or { key, label, color } objects. Order assigns the palette slots.

  • Alice
  • Bob
  • Chris

Colors are the library's own semantic ones — primary, secondary, success, warning, error, info, pending, neutral — and any shade of them, primary-400 through primary-950, exactly as the bg-* utilities spell them. Set color per series (or per item) to pin one; leave it unset to take the next slot of the default sequence. neutral and secondary are never handed out automatically, so an unlabelled series never lands on them.

The enclosed area is not a total — it depends on the order the axes happen to sit in. Don't rank profiles by how big they look.

ARIA label

required

ariaLabel is required. A radar is a shape, and without a sentence naming what it plots there's nothing to read.

  • Alice
  • Bob

ARIA description

ariaDescription is the detail the label shouldn't carry — which profile leads where.

Alice leads on speed and recovery; Bob on accuracy, endurance and consistency.
  • Alice
  • Bob

Min

min pins the radial axis's floor. It defaults to zero, so this is only for the rare axis whose true floor sits above it.

  • Alice
  • Bob

Max

max pins the radial axis's ceiling. Radar polygons are only comparable when the scale is fixed, so set it whenever the axes have a known full range — a 0–100 score shouldn't rescale itself because today's best value happens to be 90.

  • Alice
  • Bob
  • Alice
  • Bob

Five to eight axes is the readable range. Below five, a BarChart compares the values more precisely; above eight, the polygon turns to mush and the axis labels collide.

Fill

fill shades each polygon's interior, which reads as an area — right for one or two profiles. Turn it off past two or three, where overlapping translucent shapes stop resolving into anything.

  • Alice
  • Bob
  • Chris
  • Alice
  • Bob
  • Chris

Turn fill off past two or three profiles, where the overlapping fills stop resolving and the outlines carry the comparison better.

Fill opacity

fillOpacity sets how solid each filled polygon is. Lower it when two profiles overlap heavily.

Stroke width

strokeWidth is the polygon outline, in pixels. Worth raising once the fill is off and the outline is all there is.

  • Alice
  • Bob
  • Chris
  • Alice
  • Bob
  • Chris

Rings

rings sets how many rings the grid draws — the radar's equivalent of tick density.

Polygon grid

polygonGrid draws the rings as polygons rather than circles, matching the shape the data traces. Circles read cleaner; polygons make it easier to judge a value against its own spoke.

  • Alice
  • Bob
  • Alice
  • Bob

Guides

guides are the rings, spokes and axis labels. Off, the polygons float on their own — a decorative shape rather than a chart.

  • Alice
  • Bob

guides="false" drops the rings, spokes and axis labels, leaving the profile outlines alone. The polygon keeps its radius either way — a radar reserves no axis margins to reclaim, unlike the cartesian charts.

Animate

animate is on by default: the profiles swell out of the centre on the first draw and ease into their new shape. Roll new values to compare it with the chart on the right, which has it off. Only the marks move — axes, tooltips and labels always read the real numbers — and a reader who has asked their system for reduced motion gets no motion either way.

  • Alice
  • Bob
  • Alice
  • Bob

Legend

legend is on by default from two profiles up, and off for one — a single polygon needs no key.

Legend position

legendPosition sets where the legend sits relative to the plot.

  • Alice
  • Bob

Legend align

legendAlign places the key horizontally. Centre suits a radar, which is itself a centred shape.

  • Alice
  • Bob
  • Alice
  • Bob
  • Alice
  • Bob

Legend orientation

legendOrientation flows the entries in a row or a column. vertical gives each profile its own line.

  • Alice
  • Bob
  • Chris

Legend group

legendGroup names a group that a standalone UiChartLegend with the same group belongs to, so the legend can sit anywhere — here above the plot — and still dim the other profiles while you hover an entry. The chart hands the legend its entries, colors included, so it needs no items. Switch the chart's own legend off if you don't want two.

Height

height is the plot's height in pixels; the radar is sized to fit inside it. It's ignored once aspectRatio is set.

Aspect ratio

aspectRatio sizes the chart from its container's width instead of a fixed height.

  • Alice
  • Bob

Loading

loading is a skeleton at the chart's exact height; an empty data array gets the empty state instead.

  • Alice
  • Bob
No data to display
  • Alice
  • Bob

API Reference

Generated from the component's source — props, slots and emits as the component actually declares them.

Props

Prop
Type
Default
Description
datarequired
Record<string, unknown>[]
—
One object per axis, with one field per profile. Every axis shares one radial scale, so the fields have to be comparable quantities — normalize to a common range first if they aren't, or the shape means nothing. Five to eight axes is the readable range; below that a bar chart compares them more precisely, above it the polygon turns to mush.
categoryKeyrequired
string
—
Field holding each row's axis name.
seriesrequired
ChartSeriesInput[]
—
The profiles to draw.
ariaLabelrequired
string
—
What the chart shows, for screen readers. Required.
string
—
A longer accessible description, for detail the label shouldn't carry.
number
0
Lowest value the radial axis reaches. Radar polygons are only comparable when the scale starts at zero, so this defaults there — override it only when the axes have a floor other than zero.
number
—
Highest value the radial axis reaches. Defaults to the data's own max.
boolean
true
Fills each polygon. Turn it off past two or three profiles.
number
0.18
Fill opacity for each polygon.
number
2
Stroke width in pixels.
number
4
How many rings the grid draws.
boolean
true
Draws the rings as polygons rather than circles, matching the shape the data traces.
boolean
true
Draws the rings, spokes and axis labels.
boolean
true
Expands the profiles out of the centre on the first draw, and eases them to their new shape whenever the data changes. Readers who ask their system for reduced motion get no animation either way.
boolean
—
Shows the legend. Defaults to on for two or more profiles.
"top" | "bottom"
'bottom'
Where the legend sits relative to the plot.
"start" | "center" | "end"
'center'
Horizontal placement of the legend.
"horizontal" | "vertical"
'horizontal'
How the legend entries flow.
string
—
Names the group a `<UiChartLegend group="…">` elsewhere on the page belongs to, so hovering its entries dims this chart's other marks. Set it — usually with `:legend="false"` — to place the legend anywhere you like instead of under the plot.
number
340
Height of the plot in pixels. Ignored when `aspectRatio` is set.
number
—
Width-to-height ratio, sizing the chart from its container's width.
boolean
false
Replaces the plot with a skeleton of the same height.

Types

ts
interface ChartPlot {
    x: number;
    y: number;
    width: number;
    height: number;
    /** Right edge, since marks need it more often than the width. */
    right: number;
    /** Bottom edge, which is also the x axis' baseline. */
    bottom: number;
}
ts
type ChartSeriesInput = string | ChartSeries;