Join our Discord community
Pie chart

Centered Text Donut Chart

Donut chart with centered text displaying total value and dynamic calculations. Perfect for React applications requiring data summaries with Next.js integration and TypeScript support.

Powered by

Loading component...

Installation

npx shadcn@latest add https://www.shadcn.io/registry/pie-chart-09.json
npx shadcn@latest add https://www.shadcn.io/registry/pie-chart-09.json
pnpm dlx shadcn@latest add https://www.shadcn.io/registry/pie-chart-09.json
bunx shadcn@latest add https://www.shadcn.io/registry/pie-chart-09.json

Features

  • Centered text display showing calculated total visitors count in donut center
  • Dynamic calculation using React.useMemo for efficient total computation
  • Custom Label component with viewBox positioning for accurate centering
  • Styled text layers with large bold number and smaller muted description
  • Responsive text positioning adapting to chart dimensions automatically
  • TypeScript support with React hooks and proper type definitions

Use Cases

This free open source React component works well for:

  • KPI dashboards - Display total metrics with categorical breakdown built with Next.js
  • Summary displays - Show aggregate values alongside proportional data using TypeScript and Tailwind CSS
  • Performance metrics - Present totals with supporting category information
  • Executive summaries - Provide key numbers with visual data context

API Reference

ChartPieDonutText

PropTypeDefaultDescription
classNamestring-Additional CSS classes for the container

Dynamic Total Calculation

The component calculates totals using React.useMemo:

const totalVisitors = React.useMemo(() => {
  return chartData.reduce((acc, curr) => acc + curr.visitors, 0)
}, [])

Center Text Implementation

Custom Label component with viewBox positioning:

<Label
  content={({ viewBox }) => {
    if (viewBox && "cx" in viewBox && "cy" in viewBox) {
      return (
        <text
          x={viewBox.cx}
          y={viewBox.cy}
          textAnchor="middle"
          dominantBaseline="middle"
        >
          <tspan
            x={viewBox.cx}
            y={viewBox.cy}
            className="fill-foreground text-3xl font-bold"
          >
            {totalVisitors.toLocaleString()}
          </tspan>
          <tspan
            x={viewBox.cx}
            y={(viewBox.cy || 0) + 24}
            className="fill-muted-foreground"
          >
            Visitors
          </tspan>
        </text>
      )
    }
  }}
/>

Implementation Notes

  • Total automatically recalculates when data changes
  • Text positioned using viewBox coordinates for proper centering
  • Number formatted with locale string for thousand separators
  • Uses 3xl font size and bold weight for primary number
  • Secondary label positioned 24px below with muted styling
  • Maintains donut shape with 60px inner radius and 5px stroke
  • Component designed without background for flexible integration