Ring Chart

A composable multi-ring progress chart with animated arcs, hover interactions, and a reusable legend component

12,847Total Sessions

Sessions by Channel

Organic4,25085%
Paid3,12062%
Email2,10042%
Social1,58032%
Referral1,05021%
Direct74715%

Installation

pnpm dlx shadcn@latest add @bklit/ring-chart

Usage

The Ring Chart uses a composable API similar to other charts in the library. Build charts by combining components:

import { RingChart, Ring, RingCenter } from "@bklitui/ui/charts";

const data = [
  { label: "Organic", value: 4250, maxValue: 5000, color: "#0ea5e9" },
  { label: "Paid", value: 3120, maxValue: 5000, color: "#a855f7" },
  { label: "Email", value: 2100, maxValue: 5000, color: "#f59e0b" },
];

export default function SessionsChart() {
  return (
    <RingChart data={data} size={300}>
      {data.map((item, index) => (
        <Ring key={item.label} index={index} />
      ))}
      <RingCenter defaultLabel="Total Sessions" />
    </RingChart>
  );
}

Components

RingChart

The root component that provides context to all children.

PropTypeDefaultDescription
dataRingData[]requiredArray of ring data items
sizenumberautoFixed size in pixels (uses parent if not set)
strokeWidthnumber12Width of each ring
ringGapnumber6Gap between rings
baseInnerRadiusnumber60Inner radius of the innermost ring
hoveredIndexnumber | null-Controlled hover state
onHoverChange(index: number | null) => void-Hover state callback
classNamestring""Additional CSS class

Ring

Renders an individual ring with background track and animated progress arc.

PropTypeDefaultDescription
indexnumberrequiredIndex of the ring in the data array
colorstringfrom data/paletteOptional color override
animatebooleantrueEnable animation on mount
showGlowbooleantrueShow glow effect on hover
lineCap"round" | "butt""round"Line cap style for ring ends

RingCenter

Displays the total or hovered value in the center of the chart.

PropTypeDefaultDescription
defaultLabelstring"Total"Label shown when not hovering
formatValue(value: number) => stringtoLocaleString()Format function for values
childrenfunction-Custom render function
classNamestring""Additional CSS class

Legend

A composable legend component for ring charts, pie charts, and other visualizations. See the full Legend documentation for all components and options.

Data Shape

interface RingData {
  label: string;      // Display label
  value: number;      // Current value
  maxValue: number;   // Maximum value (for percentage)
  color?: string;     // Optional color (falls back to palette)
}

interface LegendItem {
  label: string;
  value: number;
  maxValue?: number;  // Required if showProgress is true
  color: string;
}

See the charts gallery for custom colors, legend sync, and center content variations.

Theming

The Ring Chart uses CSS variables for theming. The ring background uses --chart-ring-background, and ring colors default to --chart-1 through --chart-5:

:root {
  --chart-ring-background: oklch(0.9 0.005 260 / 0.25);
  --chart-1: oklch(0.646 0.222 41.116);
  --chart-2: oklch(0.6 0.118 184.704);
  --chart-3: oklch(0.398 0.07 227.392);
  --chart-4: oklch(0.828 0.189 84.429);
  --chart-5: oklch(0.769 0.188 70.08);
}

.dark {
  --chart-ring-background: oklch(0.35 0.01 260 / 0.25);
  --chart-1: oklch(0.488 0.243 264.376);
  --chart-2: oklch(0.696 0.17 162.48);
  --chart-3: oklch(0.769 0.188 70.08);
  --chart-4: oklch(0.627 0.265 303.9);
  --chart-5: oklch(0.645 0.246 16.439);
}

Animation

The ring chart features a multi-phase animation on mount:

  1. Ring Expansion - Background rings scale in with staggered timing
  2. Progress Arcs - Progress arcs animate from 0 to their target value
  3. Center Content - Value and label fade in
  4. Legend - Items slide in from the right with progress bars filling

All animations use spring physics for natural motion.

Dependencies

pnpm add @visx/shape @visx/group @visx/responsive motion