Skip to content

Interactive Answers

Radar Chart

Scores across several axes as a polygon, with a dashed bar to meet and each member's values as dots on the spokes.

2 variantsMIT

Preview

Team skills

Design · Q3 review · 4 people

3.2bar 3.1

Craft3.8Systemsthinking3.8Product sense3.3Collaboration2.5Communication2.8Leadership3.0
Team averageSenior barJRMKLWAS
Team skills
AxisTeam averageSenior barJae RheeMira KovacLeo WrightAna Soto
Craft3.83.54.04.04.03.0
Systems thinking3.83.04.04.04.03.0
Product sense3.33.03.04.03.03.0
Collaboration2.53.03.02.02.03.0
Communication2.83.03.03.03.02.0
Leadership3.03.04.03.03.02.0

Installation

Copies the component into components/ui and installs its dependencies and theme tokens.

pnpm dlx shadcn@latest add https://tuffui.com/r/radar-chart.json

Usage

Pass your own data and wire the callbacks to your agent runtime.

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

export function TeamSkills({ review }: { review: SkillsReview }) {
  return (
    <RadarChart
      title="Team skills"
      subtitle={`${review.team} · ${review.cycle}`}
      axes={review.skills} // "Craft", "Systems thinking", …
      max={4}
      series={{ id: "avg", label: "Team average", values: review.average }}
      baseline={{ label: "Senior bar", values: review.bar }}
      members={review.people.map((p) => ({
        id: p.id,
        label: p.initials,
        name: p.name,
        values: p.scores,
      }))}
      headline={{ value: review.overall.toFixed(1), caption: "bar 3.0" }}
      onSelect={(axis) => openRubric(review.skills[axis])}
    />
  );
}

Props

PropTypeDefaultDescription
axes*string[]—One label per axis, clockwise from the top. Five to eight read best.
max*number—Top of the scale, drawn as the outer ring. Up to 10 gets a ring per step, otherwise four.
series*RadarSeries—The filled polygon, e.g. a team average. Its values label each axis.
baseline{ label: string; values: number[] }—A dashed polygon to measure against, like the bar for a level.
membersRadarMember[][]Individual values drawn as dots on each spoke. Hovering an axis lists them all.
title*string—Header title.
subtitlestring—Secondary line under the title.
headline{ value: string; caption?: string }—Number on the right of the header, with a short caption.
format(value: number) => stringv.toFixed(1)Formats every value: axis labels, tooltip and screen reader text.
onSelect(axis: number) => void—Called when an axis is hovered or reached with the arrow keys.
classNamestring—Extra classes for the root element.
type RadarSeries = {
  id: string;
  label: string;
  values: number[]; // one per axis, 0…max
  color?: string;   // defaults to brand
};

type RadarMember = {
  id: string;
  label: string;    // short, e.g. initials
  name?: string;    // full name for screen readers
  values: number[]; // one per axis, 0…max
  color?: string;   // defaults to blue, teal, purple, gold
};