2

Donut Chart

PreviousNext

Animated ring chart with interactive segments, tooltips, and center content.

100Total
"use client"

import { DonutChart } from "@/components/ui/charts"

const data = [
  { label: "Chrome", value: 62.5, color: "#2563eb" },
  { label: "Safari", value: 19.3, color: "#3b82f6" },
  { label: "Firefox", value: 4.2, color: "#60a5fa" },
  { label: "Edge", value: 4.1, color: "#93c5fd" },
  { label: "Other", value: 9.9, color: "#bfdbfe" },
]

export function DonutChartDemo() {
  return (
    <div className="w-full max-w-md">
      <DonutChart data={data} innerRadius={0.65} showLabels showTotal animate />
    </div>
  )
}

About

The Donut Chart displays data as proportional segments in a ring, with a hollow center for key metrics. Features smooth animations, interactive hover states, and multiple style variants.

Features:

  • Animated entrance - Smooth animation on mount
  • Interactive segments - Hover to highlight and see details
  • Proper tooltips - Detailed tooltips following cursor
  • Center content - Display totals or selected segment info
  • Multiple variants - Default, gradient, and separated styles
  • Label lines - Auto-positioned labels for small segments

Installation

pnpm dlx shadcn@latest add https://ui.simplifying.ai/r/donut-chart.json

Usage

import { DonutChart } from "@/components/ui/charts"
 
const data = [
  { label: "Chrome", value: 62.5, color: "#4285F4" },
  { label: "Safari", value: 19.3, color: "#FF9500" },
  { label: "Firefox", value: 4.2, color: "#FF7139" },
  { label: "Edge", value: 4.1, color: "#0078D7" },
  { label: "Other", value: 9.9, color: "#6B7280" },
]
 
export function Example() {
  return <DonutChart data={data} innerRadius={0.65} showLabels animate />
}

Variants

Gradient Style

Segments with gradient fills for a modern look.

$120kBudget
"use client"

import { DonutChart } from "@/components/ui/charts"

const data = [
  { label: "Sales", value: 45000, color: "#2563eb" },
  { label: "Marketing", value: 32000, color: "#3b82f6" },
  { label: "Development", value: 28000, color: "#60a5fa" },
  { label: "Operations", value: 15000, color: "#93c5fd" },
]

export function DonutChartGradientDemo() {
  return (
    <div className="w-full max-w-md">
      <DonutChart
        data={data}
        variant="gradient"
        innerRadius={0.55}
        showLabels
        animate
        valueFormatter={(value) => `$${(value / 1000).toFixed(0)}k`}
        centerLabel="Budget"
        showTotal={false}
        centerValue="$120k"
      />
    </div>
  )
}

Separated Segments

Segments with gaps between them.

156Tasks
"use client"

import { DonutChart } from "@/components/ui/charts"

const data = [
  { label: "Completed", value: 68, color: "#2563eb" },
  { label: "In Progress", value: 22, color: "#3b82f6" },
  { label: "Pending", value: 10, color: "#60a5fa" },
]

export function DonutChartSeparatedDemo() {
  return (
    <div className="w-full max-w-md">
      <DonutChart
        data={data}
        variant="separated"
        innerRadius={0.7}
        cornerRadius={8}
        showLabels
        animate
        centerLabel="Tasks"
        centerValue="156"
        showTotal={false}
      />
    </div>
  )
}

Half Donut (Gauge)

Semi-circle donut for gauge-style displays.

73%Storage
"use client"

import { DonutChart } from "@/components/ui/charts"

const data = [
  { label: "Used", value: 73, color: "#2563eb" },
  { label: "Free", value: 27, color: "#bfdbfe" },
]

export function DonutChartHalfDemo() {
  return (
    <div className="w-full max-w-md">
      <DonutChart
        data={data}
        innerRadius={0.75}
        startAngle={-Math.PI}
        endAngle={0}
        animate
        showLegend={false}
        centerLabel="Storage"
        centerValue="73%"
        showTotal={false}
        height={250}
      />
    </div>
  )
}

API Reference

PropTypeDefaultDescription
dataDonutChartDataPoint[]requiredArray of data points
innerRadiusnumber0.6Inner radius ratio (0-1). 0.6 = 60% hollow
variant"default" | "gradient" | "separated""default"Visual style
showLabelsbooleanfalseShow percentage labels on segments
showLabelLinesbooleantrueShow label lines for small segments
centerLabelReactNode-Label text in center
centerValueReactNode-Value text in center
showTotalbooleantrueShow total in center when nothing hovered
animatebooleantrueAnimate on mount
animationDurationnumber750Animation duration in ms
padAnglenumber0.02Gap between segments (radians)
cornerRadiusnumber4Rounded corners on segments
startAnglenumber-π/2Starting angle (top)
endAnglenumber1.5πEnding angle
sortValuesbooleanfalseSort segments by value
valueFormatterfunction-Custom value formatter
onSegmentClickfunction-Click handler for segments
activeIndexnumber-Controlled active segment

Data Format

interface DonutChartDataPoint {
  label: string // Segment label
  value: number // Segment value
  color?: string // Optional custom color
}

Customization

Custom Colors

const data = [
  { label: "Sales", value: 45, color: "#8B5CF6" },
  { label: "Support", value: 30, color: "#EC4899" },
  { label: "Other", value: 25, color: "#10B981" },
]

Custom Value Formatter

<DonutChart
  data={data}
  valueFormatter={(value, total) => `$${value.toLocaleString()}`}
/>

Half Donut (Gauge Style)

<DonutChart
  data={data}
  startAngle={-Math.PI}
  endAngle={0}
  innerRadius={0.75}
  height={250}
/>

Click Handling

<DonutChart
  data={data}
  onSegmentClick={(item, index) => {
    console.log(`Clicked: ${item.label}`)
  }}
/>

Notes

  • The donut chart automatically animates on mount unless animate={false} is set
  • Use innerRadius between 0.5-0.75 for optimal visual balance (0.6 is recommended)
  • Small segments (< 5%) automatically get label lines when showLabelLines={true}
  • The gradient variant applies radial gradients to each segment for a modern look
  • For gauge-style displays, use half-circle configuration with startAngle and endAngle
  • Segment percentages are calculated automatically from values
  • The center content updates on hover to show individual segment details