Polar shapes

Polar shapes

Everything that plots around a center point instead of on an x/y grid. Pies, donuts, and radars all live inside a separate <PolarChartContainer>.

PolarChartContainer

The polar equivalent of <ChartContainer>. Measures its own size via ResizeObserver, computes a center (cx, cy) and outer radius, and exposes them to children via a separate polar context.

<PolarChartContainer
  data={products}
  valueKey="revenue"    // required for Pie, omit for Radar
  innerRadius={70}      // 0 = pie, >0 = donut
  padding={16}          // gap from container edge, default 20
>
  <Pie colors={COLORS} />
</PolarChartContainer>

The valueKey prop is typed as KeysOfType<T, number>, so string-valued keys are rejected at compile time. Read via usePolarChartContext() in custom components.

Pie & Donut

A pie chart with innerRadius=0; a donut with any positive value. The label render prop receives the slice centroid (a 2-element pixel offset from the pie center) so you can position text at each wedge’s visual middle.

<Pie<Row>
  colors={["#5eead4", "#38bdf8", "#a78bfa", "#f472b6"]}
  label={({ centroid, datum }) => (
    <text
      x={centroid[0]} y={centroid[1]}
      textAnchor="middle" dy="0.32em"
      fontSize={12} fill="#000"
    >
      {datum.category}
    </text>
  )}
/>

Slices are drawn in data order (we call d3.pie().sort(null) under the hood), so the visual order matches whatever order you pass to data.

Radar

A closed polygon connecting one data row’s values across multiple numeric axes. Pass axes (the keys to plot) and a maxValue for consistent scaling. For multi-series overlays, add multiple <Radar> children with different rowIndex props.

<PolarChartContainer data={players} padding={24}>
  <RadarGrid axesCount={5} rings={4} />
  <RadarAxes axes={["speed", "power", "defense", "magic", "agility"]} />
  <Radar
    axes={["speed", "power", "defense", "magic", "agility"]}
    rowIndex={0}
    fill="#5eead4" fillOpacity={0.25}
    stroke="#5eead4"
  />
  <Radar
    axes={["speed", "power", "defense", "magic", "agility"]}
    rowIndex={1}
    fill="#38bdf8" fillOpacity={0.25}
    stroke="#38bdf8"
  />
</PolarChartContainer>

Omit rowIndex to plot the first row by default. Each <Radar> owns its own hover state, so a <PolarTooltip> below them can react to whichever polygon the user is over.

RadarGrid

Background concentric rings for radar charts. Configurable ring count and shape (polygon or circle). Renders behind everything else. Place it as the first child of the container.

<RadarGrid axesCount={5} rings={4} shape="polygon" />

RadarAxes

Spokes from the center to the outer radius, plus labels beyond each endpoint. Text anchor flips automatically based on each label’s angular position so nothing crowds the center.

<RadarAxes axes={["speed", "power", "defense", "magic", "agility"]} />