Donut

Proportions chart. Hand-rolled SVG, no dependencies. Each segment is a same-radius circle with a stroke-dasharray arc and per-segment rotation. Set thickness to 50 for a pie chart. Pair with the Donut Legend list for a side-by-side breakdown.

a11y (built in): the SVG renders as one role="img" node whose aria-label is a generated summary of the whole series (Donut chart of 100: Mobile: 60, Desktop: 32, Tablet: 8, or Donut chart (no data) when empty), so the chart is never a silent graphic; each arc additionally carries a <title> for the native hover tooltip. The .lb-donut__center slot survives every re-render as ordinary DOM text, so the headline number is read as text rather than baked into the drawing.

Usage: <div data-lb-donut> with a <script type="application/json"> child holding { data, colors, thickness, gap }. data is an array of { label, value }.


Default

Three segments, default thickness, default colors from the data palette.

With center value

Add a .lb-donut__center child to the donut for the headline number — typical for goal-vs-target or percent-complete charts.

68%
Complete

Thickness — thin ring → pie

The thickness config (0–50, in viewBox units) controls the donut hole. 50 closes the hole entirely (pie chart).

With legend

Compose the donut with a .lb-donut-legend list. Segments take --lb-data-1…--lb-data-8 in data order unless the config passes a colors array, so give each swatch the matching var(--lb-data-N) — as the demo below does.

  • Acquisition 42%
  • Retention 28%
  • Expansion 20%
  • Other 10%

In a Card — quota widget

The donut + center value pattern, wrapped in a Card with a label and caption.

Storage used
42.8 GB of 100 GB allocated
43%
  • Used 42.8 GB
  • Free 57.2 GB