DonutChart
DonutChart is a component for drawing donut charts to compare multiple sets of data.
interface Data {
browser: string
visits: number
fill?: CSSProps["fill"]
}
const series = useMemo<DonutChart.DonutProps<Data>[]>(
() => [{ dataKey: "visits", nameKey: "browser" }],
[],
)
const data = useMemo<Data[]>(
() =>
DonutChart.mergeData([
{
browser: "chrome",
visits: faker.number.int({ max: 5000, min: 1000 }),
},
{
browser: "edge",
visits: faker.number.int({ max: 5000, min: 1000 }),
},
{
browser: "firefox",
visits: faker.number.int({ max: 5000, min: 1000 }),
},
{
browser: "opera",
visits: faker.number.int({ max: 5000, min: 1000 }),
},
{
browser: "safari",
visits: faker.number.int({ max: 5000, min: 1000 }),
},
{
browser: "other",
visits: faker.number.int({ max: 5000, min: 1000 }),
},
]),
[],
)
return <DonutChart.Root data={data} series={series} />
Usage
import { DonutChart } from "@yamada-ui/react"
import { DonutChart } from "@/components/ui"
import { DonutChart } from "@workspaces/ui"
<DonutChart.Root>
<DonutChart.Donut>
<DonutChart.LabelList />
</DonutChart.Donut>
<DonutChart.Label />
<DonutChart.Tooltip />
<DonutChart.Legend />
</DonutChart.Root>
Composition
const data = useMemo<Data[]>(
() =>
createPolarChartData().map((item, index) => ({
...item,
fill: ["cyan", "green", "orange", "red", "blue", "gray"][index],
})),
[],
)
return (
<DonutChart.Root>
<DonutChart.Donut data={data} dataKey="visits" nameKey="browser">
<DonutChart.LabelList color="white" dataKey="browser" />
<Text as="span">Donut Chart</Text>
</DonutChart.Donut>
<DonutChart.Tooltip />
<DonutChart.Legend />
</DonutChart.Root>
)
Change Size
const series = useMemo<DonutChart.DonutProps<Data>[]>(
() => [{ dataKey: "visits", nameKey: "browser" }],
[],
)
const data = useMemo<Data[]>(
() => DonutChart.mergeData(createPolarChartData()),
[],
)
return (
<VStack>
<For each={["xs", "sm", "md", "lg", "xl"]}>
{(size, index) => (
<DonutChart.Root key={index} data={data} series={series} size={size} />
)}
</For>
</VStack>
)
Change Color
const series = useMemo<DonutChart.DonutProps<Data>[]>(
() => [{ dataKey: "visits", nameKey: "browser" }],
[],
)
const data = useMemo<Data[]>(
() => DonutChart.mergeData(createPolarChartData(), "blue"),
[],
)
return <DonutChart.Root data={data} series={series} />
Change Sector Colors
const series = useMemo<DonutChart.DonutProps<Data>[]>(
() => [{ dataKey: "visits", nameKey: "browser" }],
[],
)
const data = useMemo<Data[]>(
() =>
createPolarChartData().map((item, index) => ({
...item,
fill: ["cyan", "green", "orange", "red", "blue", "gray"][index],
})),
[],
)
return <DonutChart.Root data={data} series={series} />
Hide Sector Stroke
To hide sector stroke lines, set sectorStroke to "none".
const series = useMemo<DonutChart.DonutProps<Data>[]>(
() => [{ dataKey: "visits", nameKey: "browser" }],
[],
)
const data = useMemo<Data[]>(
() =>
createPolarChartData().map((item, index) => ({
...item,
fill: ["cyan", "green", "orange", "red", "blue", "gray"][index],
})),
[],
)
return <DonutChart.Root data={data} sectorStroke="none" series={series} />
Add Legend
To add the legend, set withLegend to true. The default is false. To change the placement of the legend, set legendProps.placement to "start-start", "end-end", etc. The default is "start-end".
const series = useMemo<DonutChart.DonutProps<Data>[]>(
() => [{ dataKey: "visits", nameKey: "browser" }],
[],
)
const data = useMemo<Data[]>(
() =>
createPolarChartData().map((item, index) => ({
...item,
fill: ["cyan", "green", "orange", "red", "blue", "gray"][index],
})),
[],
)
return <DonutChart.Root data={data} series={series} withLegend />
Display Multiple Donuts
To display multiple donuts in one chart, set multiple entries in series.
const series = useMemo<DonutChart.DonutProps<Data>[]>(
() => [
{
dataKey: "visits",
innerRadius: "80%",
nameKey: "browser",
},
{
dataKey: "downloads",
nameKey: "browser",
innerRadius: "50%",
outerRadius: "70%",
},
],
[],
)
const data = useMemo<Data[]>(
() => DonutChart.mergeData(createPolarChartData()),
[],
)
return <DonutChart.Root data={data} series={series} />
Add Label
To display labels, set label of series or donutProps.label to true. The default is false.
const series = useMemo<DonutChart.DonutProps<Data>[]>(
() => [{ dataKey: "visits", nameKey: "browser" }],
[],
)
const data = useMemo<Data[]>(
() =>
createPolarChartData().map((item, index) => ({
...item,
fill: ["cyan", "green", "orange", "red", "blue", "gray"][index],
})),
[],
)
return (
<DonutChart.Root data={data} donutProps={{ label: true }} series={series} />
)
Add Label Line
To display label lines, set labelLine of series or donutProps.labelLine to true. The default is false.
const series = useMemo<DonutChart.DonutProps<Data>[]>(
() => [{ dataKey: "visits", nameKey: "browser" }],
[],
)
const data = useMemo<Data[]>(
() =>
createPolarChartData().map((item, index) => ({
...item,
fill: ["cyan", "green", "orange", "red", "blue", "gray"][index],
})),
[],
)
return (
<DonutChart.Root
data={data}
donutProps={{ label: true, labelLine: true }}
series={series}
/>
)
Change Label Offset
To change the label offset, set label.offset of series or donutProps.label.offset to a number. The default is 0.
const series = useMemo<DonutChart.DonutProps<Data>[]>(
() => [{ dataKey: "visits", nameKey: "browser" }],
[],
)
const data = useMemo<Data[]>(
() =>
createPolarChartData().map((item, index) => ({
...item,
fill: ["cyan", "green", "orange", "red", "blue", "gray"][index],
})),
[],
)
return (
<DonutChart.Root
data={data}
donutProps={{ label: { offset: 12 } }}
series={series}
/>
)
Add Label List
To display values with label list, set labelList to true of series or donutProps.labelList. The default is false.
const series = useMemo<DonutChart.DonutProps<Data>[]>(
() => [{ dataKey: "visits", nameKey: "browser" }],
[],
)
const data = useMemo<Data[]>(
() =>
createPolarChartData().map((item, index) => ({
...item,
fill: ["cyan", "green", "orange", "red", "blue", "gray"][index],
})),
[],
)
return (
<DonutChart.Root
data={data}
donutProps={{ labelList: { color: "white" } }}
series={series}
/>
)
Center Label
const series = useMemo<DonutChart.DonutProps<Data>[]>(
() => [{ dataKey: "visits", nameKey: "browser" }],
[],
)
const data = useMemo<Data[]>(
() => DonutChart.mergeData(createPolarChartData()),
[],
)
const total = useMemo(
() => data.reduce((acc, { visits }) => acc + visits, 0),
[data],
)
return (
<VStack>
<DonutChart.Root data={data} series={series}>
<DonutChart.Label fontSize="5xl" fontWeight="bold" position="center">
Visitors
</DonutChart.Label>
</DonutChart.Root>
<DonutChart.Root data={data}>
<DonutChart.Donut dataKey="visits" nameKey="browser">
<DonutChart.Label
content={({ className, viewBox }) => {
if (!viewBox) return null
if (!("cx" in viewBox) || !("cy" in viewBox)) return null
return (
<text
className={className}
dominantBaseline="middle"
textAnchor="middle"
x={viewBox.cx}
y={viewBox.cy}
>
<styled.tspan asChild fontSize="6xl" fontWeight="bold">
<tspan x={viewBox.cx} y={viewBox.cy}>
{total.toLocaleString()}
</tspan>
</styled.tspan>
<styled.tspan asChild color="fg.muted" fontSize="xl">
<tspan x={viewBox.cx} y={viewBox.cy + 36}>
Visitors
</tspan>
</styled.tspan>
</text>
)
}}
/>
</DonutChart.Donut>
</DonutChart.Root>
</VStack>
)
Change Padding Angle
To change the padding angle, set paddingAngle of series or donutProps.paddingAngle to a number. The default is 0.
const series = useMemo<DonutChart.DonutProps<Data>[]>(
() => [{ dataKey: "visits", nameKey: "browser" }],
[],
)
const data = useMemo<Data[]>(
() => DonutChart.mergeData(createPolarChartData()),
[],
)
return (
<DonutChart.Root
data={data}
donutProps={{ paddingAngle: 15 }}
series={series}
/>
)
Change Start Angle
To change the start angle, set startAngle of series or donutProps.startAngle to a number. The default is 90.
const series = useMemo<DonutChart.DonutProps<Data>[]>(
() => [{ dataKey: "visits", nameKey: "browser" }],
[],
)
const data = useMemo<Data[]>(
() => DonutChart.mergeData(createPolarChartData()),
[],
)
return (
<DonutChart.Root data={data} donutProps={{ startAngle: 0 }} series={series} />
)
Change End Angle
To change the end angle, set endAngle of series or donutProps.endAngle to a number. The default is -270.
const series = useMemo<DonutChart.DonutProps<Data>[]>(
() => [{ dataKey: "visits", nameKey: "browser" }],
[],
)
const data = useMemo<Data[]>(
() => DonutChart.mergeData(createPolarChartData()),
[],
)
return (
<DonutChart.Root
data={data}
donutProps={{ endAngle: -180 }}
series={series}
/>
)
Change Inner Radius
To change the inner radius, set innerRadius of series or donutProps.innerRadius to a number or string. The default is "70%".
const series = useMemo<DonutChart.DonutProps<Data>[]>(
() => [{ dataKey: "visits", nameKey: "browser" }],
[],
)
const data = useMemo<Data[]>(
() => DonutChart.mergeData(createPolarChartData()),
[],
)
return (
<DonutChart.Root
data={data}
donutProps={{ innerRadius: "50%" }}
series={series}
/>
)
Change Outer Radius
To change the outer radius, set outerRadius of series or donutProps.outerRadius to a number or string. The default is "100%".
const series = useMemo<DonutChart.DonutProps<Data>[]>(
() => [{ dataKey: "visits", nameKey: "browser" }],
[],
)
const data = useMemo<Data[]>(
() => DonutChart.mergeData(createPolarChartData()),
[],
)
return (
<DonutChart.Root
data={data}
donutProps={{ outerRadius: "80%" }}
series={series}
/>
)
Sync
To sync charts, set syncId to a string.
const series = useMemo<DonutChart.DonutProps<Data>[]>(
() => [{ dataKey: "visits", nameKey: "browser" }],
[],
)
const data = useMemo<Data[]>(
() => DonutChart.mergeData(createPolarChartData()),
[],
)
return (
<VStack>
<DonutChart.Root data={data} series={series} syncId="chart" />
<DonutChart.Root data={data} series={series} syncId="chart" />
</VStack>
)
Format
To format values and labels, use formatter.
const series = useMemo<DonutChart.DonutProps<Data>[]>(
() => [{ dataKey: "visits", nameKey: "browser" }],
[],
)
const data = useMemo<Data[]>(
() =>
createPolarChartData().map((item, index) => ({
...item,
fill: ["cyan", "green", "orange", "red", "blue", "gray"][index],
})),
[],
)
return (
<DonutChart.Root
data={data}
series={series}
donutProps={{
label: {
formatter: (_, percent) => `${(percent * 100).toFixed(0)}%`,
},
labelLine: true,
labelList: {
color: "white",
formatter: (value) => (isString(value) ? toTitleCase(value) : value),
},
}}
tooltipProps={{
formatter: (value, name = "") => [
Number(value).toLocaleString(),
toTitleCase(name),
],
}}
/>
)
Hide Tooltip
To hide the tooltip, set withTooltip to false. The default is true.
const series = useMemo<DonutChart.DonutProps<Data>[]>(
() => [{ dataKey: "visits", nameKey: "browser" }],
[],
)
const data = useMemo<Data[]>(
() => DonutChart.mergeData(createPolarChartData()),
[],
)
return <DonutChart.Root data={data} series={series} withTooltip={false} />