RadarChart
Polygon-based profile chart for scouting and editorial workflows. Use it when the story is the overall shape of a profile across ordered axes.
Canonical behaviors.
Multiple categories tint the axis labels and emit a grouped legend.
Editorial ring treatment instead of plain ring lines.
Bands render only inside the profile polygon — the classic StatsBomb scouting radar look. Optional outerRingColors adds a full-circle alternating-grey background; spoke-tick labels inside the polygon auto-invert to white bold for contrast.
Pass `series` to overlay two (or more) players. Hover any slot to see all values at once. `showVertexValues` labels every vertex with a coloured pill — useful when scouts want values visible without hovering.
Per-axis min/max normalization with raw values rather than percentiles.
Finer ring steps for pages that want a more explicit scale.
ThemeProvider restyles the chart without changing the row model.
Few metrics still render, but the radial read is much weaker.
No rows means no polygon.
RadarChart is part of the stable export union through the bounded export prop surface.
Composition patterns.
Use the shared chart-frame note seam for sample and role context instead of rebuilding prose around the card.
Shared concerns.
Choose RadarChart
Use RadarChart when axis order and overall profile shape matter more than exact bar-to-bar comparisons.
Ordering Matters
Metric order is part of the visual meaning. Reordering axes changes the shape the reader perceives.
Percentile Vs Range
Percentiles are the default scouting read. Range mode is useful only when you have defensible per-metric min/max bounds.
Composition
RadarChart is best as a standalone profile card. Use surrounding text to explain role, sample, and comparison context.
Export / Static
RadarChart is part of the stable export union, but only through the bounded export prop surface. Shared methodology notes stay in the live React path.
Responsive Behavior
Circular charts fail at the labels first. On narrower widths the polygon and
ring read should survive before dense outer text does. Use
radarChartRecipes.smallMultiples
when the surrounding layout already names the metrics.
Width pressure.
At smaller widths the polygon and ring structure should survive before dense outer labels do.
Wider layouts preserve more label separation and category-legibility around the ring.
Best-practice examples.
Minimal usage
Pass rows with percentile values and categories. The component handles the polar layout and category legend.
import { RadarChart } from "@withqwerty/campos-react";
export function PlayerRadar({ rows }) {
return <RadarChart rows={rows} />;
}
Recipe-driven comparison
Use named radar recipes for benchmark looks and comparison chrome instead of rebuilding the same prop combinations per card.
import {
mergeChartRecipeProps,
RadarChart,
radarChartRecipes,
} from "@withqwerty/campos-react";
export function PlayerRadarComparison({ series }) {
return (
<RadarChart
series={series}
{...mergeChartRecipeProps(
radarChartRecipes.statsbomb,
radarChartRecipes.comparison,
)}
/>
);
}
Public surface.
| Prop | Type | Default | Description |
|---|---|---|---|
rows | RadarChartRow[] | — | Single-profile shorthand. Equivalent to series: [{ id: 'default', rows }]. Pass this OR `series`, not both. |
series | { id, label?, rows, color? }[] | — | Multi-profile overlay. One polygon per series; default colours come from a blue/red/green palette. Each series can override via color. |
seriesColors | string[] | ['#3b82f6','#ef4444','#22c55e', …] | Palette used to auto-assign colours across series. |
showVertexValues | boolean | false | Render a coloured pill at each vertex showing the row's displayValue. Typical for scouting comparison radars where values should be readable without hovering. |
metricOrder | string[] | undefined | Explicit metric order starting at 12 o'clock, clockwise. |
categoryOrder | string[] | undefined | Explicit category grouping order for the legend and axis tinting. |
valueMode | "percentile" | "range" | "percentile" | Normalization mode. |
showLegend | boolean | auto | Show the category legend. |
showVertexMarkers | boolean | true | Show dot markers at polygon vertices. |
showAxisLabels | boolean | true | Show metric labels around the outer ring. |
ringStyle | "line" | "banded" | "banded-inside-polygon" | "line" | Concentric ring style. 'banded-inside-polygon' clips the bands to the profile polygon for the classic StatsBomb radar look; polygon fill defaults to transparent. |
ringSteps | number[] | [0.05, 0.25, 0.5, 0.75, 0.95] | Normalized positions for ring lines and ticks. |
bandSteps | number[] | same as ringSteps | Normalized positions for banded fills. |
ringColors | string[] | subtle alternating greys | Per-ring fill colors for banded radar styles. |
outerRingColors | string[] | undefined | Full-circle background band palette. Only active when ringStyle='banded-inside-polygon'. Pairs with ringColors (used inside the polygon) for the classic StatsBomb grey-background, coloured-polygon look. |
areas | RadarChartAreasStyle | — | First-class styling surface for the profile polygon and vertex markers. |
categoryColors | string[] | football scouting palette | Per-category palette for axis tinting and legend entries. |
guides | RadarChartGuidesStyle | — | First-class styling surface for rings and spokes. |
text | RadarChartTextStyle | — | First-class styling surface for outer metric labels. |
methodologyNotes | ChartMethodologyNotes | — | Shared chart-frame note regions for sample and role context. |
`methodologyNotes` are supported in the live React surface, but they stay outside the stable `ExportFrameSpec` contract.
Create a React component using Campos RadarChart. Import RadarChart and radarChartRecipes from @withqwerty/campos-react, keep row shaping outside the component, show the smallest good usage first, then one recipe-driven comparison or benchmark-look variant.