Parts of a whole, up to about six slices. The legend is a real list with value and share; hovering a slice or focusing a row shows it in the centre, clicking a row hides it. Donut, pie and half-ring variants.
Organic search 44% (1,284), Paid ads 29.5% (862), Referrals 14.8% (431), Events 6.8% (198), Partners 5% (145).
| Category | Value | Share |
|---|---|---|
| Organic search | 1,284 | 44% |
| Paid ads | 862 | 29.5% |
| Referrals | 431 | 14.8% |
| Events | 198 | 6.8% |
| Partners | 145 | 5% |
Installation
The whole kit as one package — get updates by bumping the version. Add the styles to globals.css: @import "@vamos-ui/react/styles.css";
Usage
import { DonutChart } from "@vamos-ui/react/charts";
<DonutChart title="Leads by source" data={rows} nameKey="source" valueKey="leads"
config={{ organic: { label: "Organic search" }, paid: { label: "Paid ads" } }} />All-zero data renders an empty ring in --track with "No data".
The ring itself is not focusable; the legend list is the keyboard path.
Examples
Half ring (HR)
variant="half" with the legend under it.
Full-time 67.7% (168), Part-time 16.5% (41), Contractors 10.9% (27), Interns 4.8% (12).
| Category | Value | Share |
|---|---|---|
| Full-time | 168 | 67.7% |
| Part-time | 41 | 16.5% |
| Contractors | 27 | 10.9% |
| Interns | 12 | 4.8% |
Other grouping
Beyond maxSlices the smallest slices merge into a neutral "Other".
Türkiye 40% (18,420), Germany 20.2% (9,310), United States 17.1% (7,860), United Kingdom 9% (4,120), Other 13.7% (6,320).
| Category | Value | Share |
|---|---|---|
| Türkiye | 18,420 | 40% |
| Germany | 9,310 | 20.2% |
| United States | 7,860 | 17.1% |
| United Kingdom | 4,120 | 9% |
| Other | 6,320 | 13.7% |
Custom centre (CMS)
center takes any node; byte values use format: "bytes".
Images 41.2% (41.2 GB), Video 28.7% (28.7 GB), Documents 6.3% (6.3 GB), Free 23.8% (23.8 GB).
| Category | Value | Share |
|---|---|---|
| Images | 41.2 GB | 41.2% |
| Video | 28.7 GB | 28.7% |
| Documents | 6.3 GB | 6.3% |
| Free | 23.8 GB | 23.8% |
Pie
variant="pie" — no centre, thin separators.
Mobile 61.1% (7,420), Desktop 34.5% (4,190), Tablet 4.4% (530).
| Category | Value | Share |
|---|---|---|
| Mobile | 7,420 | 61.1% |
| Desktop | 4,190 | 34.5% |
| Tablet | 530 | 4.4% |
API
DonutChart
| Prop | Type | Default |
|---|---|---|
title / data / config / state / summary / labelsSee Chart frame. config is keyed by slice id (the nameKey value). | ChartProps | — |
nameKeyRow key holding the slice id. | keyof T | — |
valueKeyRow key holding the value. | keyof T | — |
variantShape. | "donut" | "pie" | "half" | "donut" |
size120 / 180 / 240 px diameter. | "sm" | "md" | "lg" | number | "md" |
centerCentre content; the active slice replaces it while hovered or focused. | ReactNode | "total" | "none" | "total" |
centerLabelLabel under the total. | string | "Total" |
maxSlicesRest → "Other" (fg-subtle). | number | 5 |
legendLegend list position (side falls under the ring in a narrow container). | "side" | "bottom" | "none" | "side" |
formatValue format. Default: the first config entry's format. | FormatSpec | — |
activeKey / onActiveChangeControlled active slice. | string | null | — |