Radar Chart
scificn/radar-chartFreeComponent
SVG radar/spider chart with configurable axes, animated fade-in, grid polygons, and four color variants.
Live preview
live · rendered by the registry
Rendered by scificn on their own page — this is the component running, not a screenshot of it.Install it
npx shadcn@latest add https://www.scificn.dev/r/radar-chart.jsonSource
1'use client'23import * as React from 'react'4import { cn } from '@/lib/utils'56export type RadarChartVariant = 'DEFAULT' | 'ACTIVE' | 'WARNING' | 'CRITICAL'78export interface RadarChartEntry {9 axis: string10 value: number // 0–10011}1213export interface RadarChartProps extends React.HTMLAttributes<HTMLDivElement> {14 data: RadarChartEntry[]15 variant?: RadarChartVariant16 title?: string17 size?: number18 showGrid?: boolean19 showLabels?: boolean20 showValues?: boolean21}2223const VARIANT_COLORS: Record<RadarChartVariant, string> = {24 DEFAULT: 'var(--text-secondary)',25 ACTIVE: 'var(--color-green)',26 WARNING: 'var(--color-amber)',27 CRITICAL: 'var(--color-red)',28}2930const LABEL_PAD = 363132const RadarChart = React.forwardRef<HTMLDivElement, RadarChartProps>(33 (34 {35 className,36 data,37 variant = 'ACTIVE',38 title,39 size = 240,40 showGrid = true,41 showLabels = true,42 showValues = false,43 style,44 ...props45 },46 ref47 ) => {48 const [visible, setVisible] = React.useState(false)49 React.useEffect(() => {50 const id = requestAnimationFrame(() => setVisible(true))51 return () => cancelAnimationFrame(id)52 }, [])5354 const color = VARIANT_COLORS[variant]55 const cx = size / 256 const cy = size / 257 const r = size / 2 - LABEL_PAD58 const N = data.length5960 function axisAngle(i: number) {61 return (i / N) * 2 * Math.PI - Math.PI / 262 }6364 function gridPolygon(frac: number): string {65 return data66 .map((_, i) => {67 const a = axisAngle(i)68 return `${(cx + frac * r * Math.cos(a)).toFixed(2)},${(cy + frac * r * Math.sin(a)).toFixed(2)}`69 })70 .join(' ')71 }7273 const points = data.map((entry, i) => {74 const a = axisAngle(i)75 const frac = Math.max(0, Math.min(1, entry.value / 100))76 return {77 x: cx + frac * r * Math.cos(a),78 y: cy + frac * r * Math.sin(a),79 ax: cx + r * Math.cos(a),80 ay: cy + r * Math.sin(a),81 a,82 label: entry.axis,83 value: entry.value,84 }85 })8687 const dataPolygon = points.map(p => `${p.x.toFixed(2)},${p.y.toFixed(2)}`).join(' ')8889 function labelAnchor(a: number): React.SVGAttributes<SVGTextElement>['textAnchor'] {90 const c = Math.cos(a)91 if (Math.abs(c) < 0.3) return 'middle'92 return c > 0 ? 'start' : 'end'93 }9495// … truncated
More from scificn
All 33 items| Component | Registry | Kind | Access | Installs | Command |
|---|---|---|---|---|---|
| Alertalert | scificn | Components | Free | 1 dep | |
| Badgebadge | scificn | Components | Free | 1 dep | |
| Bar Chartbar-chart | scificn | Components | Free | no deps | |
| Breadcrumbbreadcrumb | scificn | Components | Free | no deps | |
| Buttonbutton | scificn | Components | Free | 2 deps | |
| Cardcard | scificn | Components | Free | no deps | |
| Checkboxcheckbox | scificn | Components | Free | 1 dep | |
| Dialogdialog | scificn | Components | Free | 1 dep |
