Pie chart with centre removed.
| Segment | Share |
|---|---|
| Segment A | 48% |
| Segment B | 32% |
| Segment C | 20% |
<div class="donut donut--first" style="--t:18;--accent:#A8E6C1;">
<svg class="donut__ring" width="140" height="140" viewBox="0 0 120 120" aria-hidden="true">
<g transform="rotate(-90 60 60)">
<circle class="donut__seg donut__seg--1" cx="60" cy="60" r="40" fill="none" stroke="#A8E6C1" stroke-width="18" stroke-dasharray="120.64 130.69" stroke-dashoffset="0" />
<circle class="donut__seg donut__seg--2" cx="60" cy="60" r="40" fill="none" stroke="#D9C8F0" stroke-width="18" stroke-dasharray="80.43 170.9" stroke-dashoffset="-120.64" />
<circle class="donut__seg donut__seg--3" cx="60" cy="60" r="40" fill="none" stroke="#BFD9F2" stroke-width="18" stroke-dasharray="50.27 201.06" stroke-dashoffset="-201.07" />
</g>
</svg>
<span class="donut__center">
<strong class="donut__total">100%</strong>
<span class="donut__total-label">total</span>
</span>
<ul class="donut__legend">
<li class="donut__item donut__item--1"><span class="donut__swatch donut__swatch--1" aria-hidden="true"></span>Segment A — 48%<span class="donut__flag">highlighted</span></li>
<li class="donut__item donut__item--2"><span class="donut__swatch donut__swatch--2" aria-hidden="true"></span>Segment B — 32%<span class="donut__flag">highlighted</span></li>
<li class="donut__item donut__item--3"><span class="donut__swatch donut__swatch--3" aria-hidden="true"></span>Segment C — 20%<span class="donut__flag">highlighted</span></li>
</ul>
<table class="donut__srtable">
<caption>Donut chart data</caption>
<thead><tr><th scope="col">Segment</th><th scope="col">Share</th></tr></thead>
<tbody>
<tr><th scope="row">Segment A</th><td>48%</td></tr>
<tr><th scope="row">Segment B</th><td>32%</td></tr>
<tr><th scope="row">Segment C</th><td>20%</td></tr>
</tbody>
</table>
</div>
<style>
.donut { font: 14px/1.4 system-ui, sans-serif; color: #241430; max-width: 320px; position: relative; }
.donut__ring { display: block; margin: 0 auto; }
@media (prefers-reduced-motion: no-preference) {
.donut__seg { transition: stroke-width .15s ease; }
}
.donut__center { position: absolute; top: 70px; left: 70px; transform: translate(-50%, -50%); display: flex; flex-direction: column; align-items: center; text-align: center; }
.donut__total { font-size: 20px; }
.donut__total-label { font-size: 11px; color: #241430aa; }
.donut__legend { list-style: none; margin: 12px 0 0; padding: 0; font-size: 13px; }
.donut__item { display: flex; align-items: center; gap: 8px; padding: 3px 0; }
.donut__swatch { width: 12px; height: 12px; border-radius: 3px; flex: none; }
.donut__swatch--1 { background: #A8E6C1; }
.donut__swatch--2 { background: #D9C8F0; background-image: repeating-linear-gradient(45deg, #241430 0 2px, transparent 2px 5px); }
.donut__swatch--3 { background: #BFD9F2; background-image: radial-gradient(#241430 1px, transparent 1px); background-size: 5px 5px; }
.donut__flag { display: none; margin-left: 4px; font-weight: 700; font-size: 11px; }
.donut__srtable { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); }
.donut--first .donut__seg--1 { stroke-width: calc(var(--t) + 6); }
.donut--first .donut__item--1 .donut__flag { display: inline; }
.donut--second .donut__seg--2 { stroke-width: calc(var(--t) + 6); }
.donut--second .donut__item--2 .donut__flag { display: inline; }
.donut--third .donut__seg--3 { stroke-width: calc(var(--t) + 6); }
.donut--third .donut__item--3 .donut__flag { display: inline; }
</style><div class="donut-tw donut-tw--first relative max-w-xs font-sans text-sm" style="--t:18;--accent:#A8E6C1;">
<svg class="block mx-auto" width="140" height="140" viewBox="0 0 120 120" aria-hidden="true">
<g transform="rotate(-90 60 60)">
<circle class="donut-tw__seg donut-tw__seg--1" cx="60" cy="60" r="40" fill="none" stroke="#A8E6C1" stroke-width="18" stroke-dasharray="120.64 130.69" stroke-dashoffset="0" />
<circle class="donut-tw__seg donut-tw__seg--2" cx="60" cy="60" r="40" fill="none" stroke="#D9C8F0" stroke-width="18" stroke-dasharray="80.43 170.9" stroke-dashoffset="-120.64" />
<circle class="donut-tw__seg donut-tw__seg--3" cx="60" cy="60" r="40" fill="none" stroke="#BFD9F2" stroke-width="18" stroke-dasharray="50.27 201.06" stroke-dashoffset="-201.07" />
</g>
</svg>
<span class="absolute flex flex-col items-center text-center" style="top:70px;left:70px;transform:translate(-50%,-50%);">
<strong class="text-xl">100%</strong>
<span class="text-[11px] text-[#241430aa]">total</span>
</span>
<ul class="list-none m-0 mt-3 p-0 text-[13px]">
<li class="donut-tw__item donut-tw__item--1 flex items-center gap-2 py-[3px]"><span class="w-3 h-3 rounded" style="background:#A8E6C1" aria-hidden="true"></span>Segment A — 48%<span class="donut-tw__flag hidden ml-1 font-bold text-[11px]">highlighted</span></li>
<li class="donut-tw__item donut-tw__item--2 flex items-center gap-2 py-[3px]"><span class="w-3 h-3 rounded" style="background:#D9C8F0;background-image:repeating-linear-gradient(45deg,#241430 0 2px,transparent 2px 5px)" aria-hidden="true"></span>Segment B — 32%<span class="donut-tw__flag hidden ml-1 font-bold text-[11px]">highlighted</span></li>
<li class="donut-tw__item donut-tw__item--3 flex items-center gap-2 py-[3px]"><span class="w-3 h-3 rounded" style="background:#BFD9F2;background-image:radial-gradient(#241430 1px,transparent 1px);background-size:5px 5px" aria-hidden="true"></span>Segment C — 20%<span class="donut-tw__flag hidden ml-1 font-bold text-[11px]">highlighted</span></li>
</ul>
<table class="absolute w-px h-px overflow-hidden" style="clip:rect(0 0 0 0)">
<caption>Donut chart data</caption>
<thead><tr><th scope="col">Segment</th><th scope="col">Share</th></tr></thead>
<tbody>
<tr><th scope="row">Segment A</th><td>48%</td></tr>
<tr><th scope="row">Segment B</th><td>32%</td></tr>
<tr><th scope="row">Segment C</th><td>20%</td></tr>
</tbody>
</table>
</div>
<style>
@media (prefers-reduced-motion: no-preference) {
.donut-tw__seg { transition: stroke-width .15s ease; }
}
.donut-tw--first .donut-tw__seg--1 { stroke-width: calc(var(--t) + 6); }
.donut-tw--first .donut-tw__item--1 .donut-tw__flag { display: inline; }
.donut-tw--second .donut-tw__seg--2 { stroke-width: calc(var(--t) + 6); }
.donut-tw--second .donut-tw__item--2 .donut-tw__flag { display: inline; }
.donut-tw--third .donut-tw__seg--3 { stroke-width: calc(var(--t) + 6); }
.donut-tw--third .donut-tw__item--3 .donut-tw__flag { display: inline; }
</style>export function DonutChart({
highlightSegment = "first",
thickness = 18,
accent = "#A8E6C1",
showCenterLabel = true,
}) {
const segs = [
{ key: "1", name: "Segment A", pct: 48, color: accent, len: 120.64, gap: 130.69, offset: 0 },
{ key: "2", name: "Segment B", pct: 32, color: "#D9C8F0", len: 80.43, gap: 170.9, offset: -120.64 },
{ key: "3", name: "Segment C", pct: 20, color: "#BFD9F2", len: 50.27, gap: 201.06, offset: -201.07 },
];
const highlightIndex = { first: "1", second: "2", third: "3" }[highlightSegment] ?? "1";
return (
<div style={{ fontFamily: "system-ui, sans-serif", color: "#241430", maxWidth: 320, position: "relative", fontSize: 14 }}>
<svg width={140} height={140} viewBox="0 0 120 120" aria-hidden="true" style={{ display: "block", margin: "0 auto" }}>
<g transform="rotate(-90 60 60)">
{segs.map((s) => (
<circle key={s.key} cx={60} cy={60} r={40} fill="none" stroke={s.color}
strokeWidth={s.key === highlightIndex ? thickness + 6 : thickness}
strokeDasharray={`${s.len} ${s.gap}`} strokeDashoffset={s.offset} />
))}
</g>
</svg>
{showCenterLabel && (
<span style={{ position: "absolute", top: 70, left: 70, transform: "translate(-50%, -50%)", display: "flex", flexDirection: "column", alignItems: "center", textAlign: "center" }}>
<strong style={{ fontSize: 20 }}>100%</strong>
<span style={{ fontSize: 11, color: "#241430aa" }}>total</span>
</span>
)}
<ul style={{ listStyle: "none", margin: "12px 0 0", padding: 0, fontSize: 13 }}>
{segs.map((s) => (
<li key={s.key} style={{ display: "flex", alignItems: "center", gap: 8, padding: "3px 0" }}>
<span aria-hidden="true" style={{ width: 12, height: 12, borderRadius: 3, background: s.color }} />
{s.name} — {s.pct}%
{s.key === highlightIndex && <span style={{ marginLeft: 4, fontWeight: 700, fontSize: 11 }}>highlighted</span>}
</li>
))}
</ul>
<table style={{ position: "absolute", width: 1, height: 1, overflow: "hidden", clip: "rect(0 0 0 0)" }}>
<caption>Donut chart data</caption>
<thead><tr><th scope="col">Segment</th><th scope="col">Share</th></tr></thead>
<tbody>
{segs.map((s) => (
<tr key={s.key}><th scope="row">{s.name}</th><td>{s.pct}%</td></tr>
))}
</tbody>
</table>
</div>
);
}