Browse documentation

Components Charts & data

DonutChart

Show a few non-overlapping parts of one whole. Choose direct labels or a capsule legend and explain what the total represents.

Client directive required No provider required

Examples

Link to this example3 presentations

Illustrative allocation of 100 budget units to initiatives. The four seed values represent parts of one budget, not independent outcome rates. A two-row legend sits within the 300 × 340 px chart.

300 × 340 px · 100%
Adoption
32%
Savings
26%
Velocity
20%
Other
22%

Preview setting only: fitting scales the whole chart. Actual size keeps the copied example’s dimensions and allows horizontal scrolling.

Preview only: surrounding canvas and spacing. All metrics are illustrative.

Choosing a presentation

Use a donut for a few non-overlapping parts of one meaningful whole. All values must use the same unit. For close comparisons, a BarChart gives readers a shared baseline; for change over an ordered sequence, use LineChart.

  • Default · legend preserves the four seed values and 300 × 340 px dimensions. Adoption, Savings and Velocity are initiatives receiving illustrative budget units, not independent outcome rates that can be added.
  • Direct labels preserves the 320 × 320 px seed and its 68/22/10 task-status split. Every task belongs to one status. Labels replace the legend.
  • Five segments · dark adds a 340 × 392 px chart of 100 illustrative project hours. The center repeats the total and the legend occupies three rows.

Both seed datasets, dimensions and label/legend choices are retained. Their outer 24 px padding is omitted because the documentation canvas supplies space. Complete copied files include their matching background, client directive and a named group explaining the illustrative units. These are examples, not CoreUX case-study claims.

Data & validation

Provide 2–5 segments. Each needs a unique non-empty string ID, a non-empty single-line label, and a finite value strictly greater than zero. Zero, negative values, duplicates and invalid geometry throw during rendering. The summed total must be finite, and every value divided by that total must remain a positive finite share; extreme number magnitudes can violate this even when individual values are finite.

Values are normalized to shares of their total. They do not need to sum to 100, and there is no domain prop. For example, values 3 and 2 produce 60% and 40%. Use one mutually exclusive allocation or status snapshot, not unrelated percentages with different denominators. Legend text, direct labels and the image name show percentages rounded to at most three decimal places; very small positive shares can round to 0% and be hard to see. Prefer a table when small differences matter.

Budget room for the ring and legend

Width and height must be finite CSS-pixel values at least 240. Height includes the legend, with further minimums when four or five segments need extra rows. Two or three segments use one column per segment; four or five use two columns. Every row reserves 56 px.

Donut legend dimensions
SegmentsLegend heightMinimum total height
2–356 px240 px
4112 px296 px
5168 px352 px

Without a legend, all valid segment counts have a 240 px height floor. These floors ensure valid geometry, not readable text. Legend capsules can clip long names; increase width and shorten labels after checking the result.

The outer radius is half the smaller of width and chart height, minus 18 px normally or 52 px with direct labels. Chart height is total height minus legend height. innerRadiusRatio must be finite from 0.4 to 0.72 inclusive; the default is 0.58. Increasing it makes the ring thinner. Center content sits in a square 1.35 times the inner radius, so keep it short and verify it fits.

Always identify the segments

The component requires direct labels or a capsule legend: showLegend=false with showLabels=false throws. Both can be enabled. Direct labels place each name and share beyond the arc midpoint; they use 10 px text, a maximum width of 92 px and no collision avoidance. Tiny adjacent shares or long names can overlap. A legend is usually clearer for crowded data.

Appearance & motion

fieldMode="light" uses navy text and ivory segment seams; fieldMode="dark" uses ivory text and navy seams. It also changes the capsule legend. The background is transparent: the copied wrapper supplies the matching ivory or navy surface. Segment colors follow categorical palette order in both modes; “At risk” and “Blocked” do not automatically get warning/error colors. Keep the labels explicit rather than treating these colors as semantic status tokens.

This video-derived component uses inline styles and SVG attributes. It has no tone, className, style, custom palette or arbitrary HTML-attribute passthrough. Wrapper utilities arrange surrounding content; they do not provide an API to restyle the ring, labels or legend.

Remotion is not required and there is no automatic animation. Omitted progress props render the completed chart. Finite progress values clamp to 0–1; non-finite values throw. sweepProgress can be one number or exactly one number per segment. Labels continue to describe the complete shares while sweeps are partial. emphasis requires a known segment ID and finite progress, dimming other segments without expanding the chosen arc. If you animate these channels, respect reduced-motion preferences and keep the data explanation available.

Props

Types and required flags below are extracted from the installed public declarations. Authored defaults are checked against the component implementation; render-time relationships are explained above.

Types and required flags extracted from the installed @coreux/ui declarations.
Prop / typeDefaultDescription
widthRequirednumberRequiredRequired finite width in CSS pixels, at least 240. Fixed geometry.
heightRequirednumberRequiredRequired finite total height in CSS pixels, at least 240. Includes the legend: four segments with a legend require 296; five require 352.
segmentsRequiredreadonly DonutChartSegment[]Required2–5 non-overlapping parts of a whole. Unique non-empty IDs, single-line labels, and finite positive values. The total and normalized shares must stay finite and positive.
innerRadiusRationumber0.58Inner radius divided by outer radius. Finite, inclusive range 0.4–0.72; a larger value makes a thinner ring.
centerContentReactNodeundefinedOptional ReactNode in a centered square sized to 1.35 × inner radius. Keep it brief and noninteractive; repeat its meaning outside the image role for assistive technology.
showLegendfalse | truetrueShows capsule labels and percentage shares. Uses 56 px per row. Turning it off requires showLabels=true.
showLabelsfalse | truefalseShows segment names and percentage shares around the ring. Reserves a 52 px margin instead of 18, making the ring smaller. Labels have 92 px maximum width and no collision avoidance.
fieldMode"light" | "dark""light"light or dark sets text, segment seams and legend appearance. Supply a matching outer surface; the component background is transparent. Categorical fills stay the same.
sweepProgressnumber | readonly number[]1One finite number, or exactly one per segment in segment order, clamped to 0–1. Controls each arc sweep; does not recalculate the underlying shares or label values.
emphasisDonutChartEmphasisundefinedOptional existing segment ID and finite progress. Dims other segments by up to 62%; does not enlarge the selected segment.
opacityProgressnumber1Finite overall opacity, clamped to 0–1. Omission shows the complete chart.
labelProgressnumber1Finite opacity/reveal for center content, direct labels and legend, clamped to 0–1. The accessible percentage label remains present.

DonutChartSegment

Types and required flags extracted from the installed @coreux/ui declarations.
Prop / typeDefaultDescription
idRequiredstringRequiredNon-empty unique segment ID, also used for emphasis matching.
labelRequiredstringRequiredOne non-empty text line. Appears in percentage labels and the image accessible name. Use short, distinct names.
valueRequirednumberRequiredFinite and strictly greater than zero. All values share units and are divided by their total. They do not have to sum to 100.

DonutChartEmphasis

Types and required flags extracted from the installed @coreux/ui declarations.
Prop / typeDefaultDescription
segmentIdRequiredstringRequiredRequired ID of a segment in this chart. Unknown IDs throw.
progressRequirednumberRequiredRequired finite number, clamped to 0–1. Other segments fade to 0.38 opacity at full emphasis.

Accessibility & layout

The outer element has an image role and a generated name listing each segment and its percentage. The SVG is hidden from assistive technology. There is no linked raw-data description, and center content is inside the image role; do not depend on that content being announced separately or put interactive controls there. The examples’ named groups supply illustrative units and raw values, including the center total.

For a published composition, add a visible title, timeframe, units, source and takeaway beside the chart. Provide a text table or download when readers need exact values, especially when percentages round small shares away. Do not rely only on color, a center number or tiny labels. The chart has no hover, selection or keyboard data controls.

Width and height are fixed pixels, with overflow clipped and no responsive breakpoints. Fit to canvas scales the entire documentation preview, including text; it does not change props or copied code. Actual size preserves the authored geometry inside a focusable scrolling region. Check your own labels at the intended output size and offer readable surrounding text at narrow widths.

Consumer setup

Browsing, previews, and copying are public. Installing the private @coreux/ui package requires repository read access and permission to use the bundled CoreUX brand fonts.

Follow the one-time installation guide for the pinned Git dependency, Tailwind v4 stylesheet setup, fonts, and troubleshooting. Keep the 'use client' directive in each example; no provider is required.

The quick start walks through a copied StatBlock in a minimal app.

Source & revision

This reference targets @coreux/ui version 0.1.0 at 06f42fd. Types come from its installed declarations; explanations and defaults are checked against this implementation.

Revision and upgrade notes · Contribution and coverage guide

View DonutChart source (repository access required)