Pie Chart

An animated pie and donut chart with staggered slice entrances, a pop-out hover, a rolled center total, and a loading state.

Traffic Sources

  • Organic4,50040%%
  • Direct3,20029%%
  • Referral2,10019%%
  • Social1,40013%%

Installation

pnpm add @blakeui/pro-react
npm install @blakeui/pro-react
yarn add @blakeui/pro-react
bun add @blakeui/pro-react

Usage

PieChart is built on visx for its arc geometry and the motion library for the animation — it does not use Recharts. It is a single component: pass a data array (one {label, value} per slice) and configure everything through props. Slices stagger-sweep open on mount, the hovered slice pops out along its bisector while the others dim, and a donut (innerRadius > 0) rolls its total through the shared odometer — hovering a slice rolls the center to that slice's value. Slice colors come from the categorical --chart-1 … --chart-5 tokens in data order (override per-datum with color); the chart's chrome maps onto BlakeUI's neutral tokens automatically.

import {PieChart} from "@blakeui/pro-react";

const sources = [
  {label: "Organic", value: 4500},
  {label: "Direct", value: 3200},
  {label: "Referral", value: 2100},
  {label: "Social", value: 1400},
];

function App() {
  return <PieChart data={sources} innerRadius={0.66} centerLabel="Total visits" />;
}

For a legend that highlights in sync with the chart, control the hover: pass hoveredIndex and onHoverChange, and drive both the chart and your legend rows from the same index (the hero demo above wires this in both directions).

Keyboard & motion

The chart is keyboard-accessible: focus it and use the arrow keys (or Home / End) to walk the slices; Escape clears the selection. The active slice is announced to screen readers through a live region. The entrance sweep, hover springs, and center odometer all respect prefers-reduced-motion — when it is set, the chart renders without animation.

Loading state

Set status="loading" to show a stroke-only skeleton ring while data resolves — a bright pulse laps the ring under a shimmering caption. Flip it to "ready" and the load→ready choreography plays: the pulse flows out, the caption exits, and the slices stagger-sweep in.

Loading traffic…
Loading traffic…
  • Organic
  • Direct
  • Referral
  • Social

API Reference

PieChart

The single chart component. Measures its container (or takes a fixed size), computes the slice arcs, and renders the SVG plus the donut's HTML center overlay.

PropTypeDefaultDescription
dataPieChartDataPoint[]One entry per slice, drawn in data order: {label, value, color?}. color overrides the positional --chart-1..5 assignment.
sizenumberFixed box size in px. Omit for responsive sizing (a square that fills the container width).
innerRadiusnumber0Donut hole size as a fraction of the outer radius (0 = solid pie, e.g. 0.66).
padAnglenumber0Padding angle between slices in radians.
cornerRadiusnumber0Corner radius of each slice in px.
startAnglenumber-Math.PI / 2Start angle in radians (0 = 12 o'clock, clockwise).
endAnglenumber(3 * Math.PI) / 2End angle in radians (the default closes a full circle from the top).
hoverOffsetnumber10Hover pop-out distance in px — also the outer padding that keeps the pop unclipped.
hoverEffect"translate" | "grow" | "none""translate"translate pops the slice outward along its bisector; grow extends its outer radius; none keeps slices still (non-hovered slices always dim).
showGlowbooleantrueGlow the hovered slice with a drop-shadow in its own color.
centerLabelstring"Total"Label under the donut's rolled total; hover swaps it for the active slice's label.
showCenterbooleantrueRender the rolled total + label in the donut hole (ignored for solid pies).
valuePrefixstringStatic text rendered before the center value (e.g. "$").
hoveredIndexnumber | nullControlled hover — the active slice index. Pair with onHoverChange for legend sync.
onHoverChange(index: number | null) => voidCalled when the active slice changes (pointer, keyboard, or a controlled legend).
animationDurationnumber1100Per-slice entrance sweep duration in ms (slices stagger 80ms apart).
status"loading" | "ready""ready"While loading, shows the skeleton ring and disables interaction. Flipping to ready plays the entrance.
loadingLabelstring""Centered caption shown while loading. Empty string hides it.

Also supports all native div HTML attributes.

On this page