StarSpoke
React star spoke chart — multivariate profile as spokes of a tiny star. Tiny accessible SVG microchart; RSC-safe static or /interactive.
StarSpoke answers "what is this entity's profile across a few metrics — and which entity in a set is the odd one out?". Spokes radiate from the center and their length encodes each value. There is no connecting polygon, ever: the enclosed area of a radar chart lies about magnitude and axis order, and the research is clear that contour-free wins for spotting outliers.
Install
import { StarSpoke } from "@microcharts/react/star-spoke";// metrics — real values under “Sample data” below<StarSpoke data={metrics} title="Product profile" />Sample data
const metrics = [ { label: "Speed", value: 0.9 }, { label: "Power", value: 0.6 }, { label: "Range", value: 0.5 }, { label: "Cost", value: 0.3 }, { label: "Ease", value: 0.7 },];Try it
When to use it
- Good for — entity profiles in small multiples, skill / capability comparison.
- Avoid for — fewer than 3 metrics (PairedBars) or precise values (MiniBar).
Sizing
Variants
locale doesn't change any in-chart mark — tip labels are metric names, never formatted numbers — but it does localize
the extremes named in the accessible summary:
Why this default
Contour-free is the point: a connecting polygon is decoration that changes the read, exaggerating area for high-variance profiles and hiding the individual spoke lengths that actually matter for comparison. One shared domain governs every spoke in a glyph — mixed-domain metrics are the caller's normalization to state, so a set of small multiples stays honestly comparable.
Every spoke sits at a fixed clock position (first at 12 o'clock, clockwise), so the axis order never shifts between instances — that fixed order, plus the default-on guide spokes, is what keeps a profile readable even where a metric's label doesn't seat. Tip labels seat at the rim, not the value tip, so a low-value spoke never drags its label into the hub. A label is dropped only when its estimated width exceeds the whole glyph; anything narrower is clamped into the reserved label ring instead, which keeps rim labels at distinct angles rather than dropping them.
Edge cases
Four homes
Accessibility
The accessible name names the extremes — "5 metrics; highest Speed (0.9), lowest Cost (0.3)." The interactive entry rotates focus through the spokes with ←/→, announcing each metric and value.
The interactive entry follows the shared interaction contract:
arrow keys rove between units on both axes, Home and End jump to the ends, and a click, tap, Enter or
Space selects a unit — pinning its readout so it survives blur, until you select it again or press Escape.
On touch, a tap pins and a drag scrubs.
Props
| Prop | Type | Notes |
|---|---|---|
| data* | { label, value }[] | 3–8 metrics on a shared domain. |
| dots | "tips" | "none" | `"tips"` draws endpoint dots to sharpen the outlier read. |
| guides | boolean | Full-length guide spokes (read-back scaffold). |
| compare | number[] | Muted ghost baseline spokes. |
| labels | boolean | Spoke labels at the tips (default true; drop out below size 44). |
| animate | boolean | interactiveOpt-in entrance motion when the chart mounts client-side — add import "@microcharts/react/motion" once. Inert on the server, on hydrated server HTML, and under prefers-reduced-motion. |
Plus the shared grammar — data, domain, color, title, summary, format — and the layout props (width, height, className, style) that every chart accepts. Interactive entries also share animate and live, and — wherever a chart has more than one navigable unit — onActive, onSelect, selectedIndex and defaultSelectedIndex; and — wherever the chart shows a hover value — readout. See the shared grammar.
Related charts
WindBarb
React wind barb chart — shaft angle for bearing and quantized WMO barbs for strength. Tiny accessible SVG microchart; RSC-safe, static-only (no /interactive entry).
MinimapStrip
React minimap strip chart — overview density with a brushable viewport. Tiny accessible SVG microchart; RSC-safe static or /interactive.