Progress Circle
A determinate ring for quota, training and run progress — six tones, a ring or gauge track, an optional centre readout, and a sweep that animates from 12 o’clock. The default tone is deliberately info: a ring that only reports a figure is informational, and a wall of them in a table should not read as a wall of switched-on states. Reach for selected when the ring is tracking progress the user is actually driving.
import { ProgressCircle } from "@pestoui/core"Tones
Only the indicator carries the tone; the track stays a hairline so a row of rings reads as one control. selected is the brand ring — the lime primary is a fill colour and stops being legible at four pixels of stroke, so the visible green stands in for it. neutral is for a ring that is chrome rather than signal.
Sizes & readout
Named sizes pin their own stroke and font size. Pass a number for anything in between — the stroke scales with the box.
Ring or gauge track
track="ring" is the default: one continuous hairline sitting behind the indicator. track="gauge" draws the remainder as its own arc instead, held off the indicator by a blank at each junction — it reads crisper at larger diameters, where a continuous track starts to look like a second value. gapPercent sizes that blank as a percent of the circumference, floored at one and a half strokes so the two round caps can never touch.
Range & formatting
min and max map an arbitrary reading onto the sweep — 38 in a 20–80 range fills 30% of the arc, and 30 is what the default readout shows. aria-valuenow still reports 38 against its own bounds, so the announced value is the real one. formatValue takes over the readout and receives both numbers, so a ring can show hours, a rating or a currency while the arc keeps tracking the percentage.
Centre slot
children replace the readout entirely — a stacked total, a glyph, a caption. The whole slot is aria-hidden, because the root already announces the reading through aria-valuetext and two live regions racing over one quantity is worse than one terse announcement. children win over showValue, so pass one or the other.
Counting the readout up
animateValue swaps the static readout for AnimatedNumber, so the number travels while the arc sweeps instead of snapping to the answer the arc is still on its way to. It counts the raw value and derives the percentage per frame, which is what lets one formatValue serve both the resting and the in-flight readout. The count eases out rather than springing — every spring here except the overdamped pair crosses its target, and a counter that crosses briefly displays a number that was never true.
Live value
The dash offset transitions, so the sweep animates on change.
Props
Pesto UI · 117 documented components