Component reference
CircularProgress
Show upload progress with a numeric value.
Preview
Live previewOptional six-digit hex. Clear to restore the preset. Check contrast with your brand color.
Changes apply to this preview only.
Upload
The ring is small enough to sit next to a label, so the label stays outside.
Quota
A success tone with the value read inside the ring.
Syncing
No known duration: the ring rotates and nothing is announced as a value.
Service health
Three small gauges, one tone per state, with their labels outside the ring.
Width adapts to the available space
"use client";
import {
Card,
CardHeader,
CardTitle,
CardDescription,
CardContent,
CircularProgress
} from "@pimolu/react";
const services = [
{ name: "API", value: 99 },
{ name: "CDN", value: 92 },
{ name: "Workers", value: 64 },
] as const;
export function DemoExample() {
return (
<div
className="grid grid-cols-[repeat(auto-fit,minmax(min(100%,280px),1fr))] gap-6 min-w-0 items-start"
>
<Card>
<CardHeader>
<CardTitle>Upload</CardTitle>
<CardDescription>
The ring is small enough to sit next to a label, so the label
stays outside.
</CardDescription>
</CardHeader>
<CardContent>
<div className="flex flex-wrap items-center gap-3 min-w-0">
<CircularProgress
label="design-system.zip"
value={68}
size="lg"
showValue
valueLabel="68 percent uploaded"
/>
<div className="grid gap-5 min-w-0">
<span className="text-sm text-muted">design-system.zip</span>
<span className="text-sm text-muted leading-relaxed">68% · 4.2 MB of 6.1 MB</span>
</div>
</div>
</CardContent>
</Card>
<Card>
<CardHeader>
<CardTitle>Quota</CardTitle>
<CardDescription>
A success tone with the value read inside the ring.
</CardDescription>
</CardHeader>
<CardContent>
<div className="flex flex-wrap items-center gap-3 min-w-0">
<CircularProgress
label="Storage quota"
value={42}
max={50}
size="lg"
variant="success"
showValue
formatValue={(value, max) => `${value}/${max}`}
/>
<span className="text-sm text-muted leading-relaxed">Go used</span>
</div>
</CardContent>
</Card>
<Card>
<CardHeader>
<CardTitle>Syncing</CardTitle>
<CardDescription>
No known duration: the ring rotates and nothing is announced as
a value.
</CardDescription>
</CardHeader>
<CardContent>
<div className="flex flex-wrap items-center gap-3 min-w-0">
<CircularProgress label="Syncing files" size="lg" variant="secondary" />
<span className="text-sm text-muted leading-relaxed">Syncing…</span>
</div>
</CardContent>
</Card>
<Card>
<CardHeader>
<CardTitle>Service health</CardTitle>
<CardDescription>
Three small gauges, one tone per state, with their labels
outside the ring.
</CardDescription>
</CardHeader>
<CardContent>
<div className="grid gap-5 min-w-0">
{
services.map((service) => (<div
key={service.name}
className="flex flex-wrap items-center gap-3 min-w-0"
>
<CircularProgress
label={service.name}
value={service.value}
size="sm"
variant={service.value >= 90
? "success"
: service.value >= 70
? "warning"
: "danger"}
/>
<span className="flex-1 min-w-0">
{service.name}
</span>
<span className="text-sm text-muted leading-relaxed">
{service.value}%
</span>
</div>))
}
</div>
</CardContent>
</Card>
</div>
);
}More examples
Different configurations and compositions using the real Pimolu API. Each preview runs independently and follows the site appearance.
Sizes
The stroke scales with the diameter, because the whole SVG scales.
Variants
The variant sets the tone of the indicator.
States
Determinate, indeterminate, formatted, clamped.
Usage
Use determinate progress for a known total and indeterminate presentation when the total is unknown.
API reference
Generated from the public TypeScript declarations. Native HTML attributes are inherited where the component extends them; this reference includes Pimolu props and selected common native attributes.
PimoluCircularProgressProps
Type source| Name | Type | Default | Description |
|---|---|---|---|
value | number | undefined | — | Current value between 0 and `max`. Leave it undefined for an indeterminate gauge. |
max | number | undefined | 100 | Upper bound. |
size | "sm" | "md" | "lg" | undefined | "md" | Visual size of the gauge. |
variant | "primary" | "secondary" | "neutral" | "success" | "warning" | "danger" | undefined | "primary" | Tone of the indicator. |
label | string | undefined | — | Accessible name of the gauge. It is not rendered: a circular gauge is too small to carry a readable label, so compose it next to the component. |
showValue | boolean | undefined | false | Display the current value in the middle. |
formatValue | ((value: number, max: number) => string) | undefined | — | Formats the readout, for example (value, max) => `${value}/${max}`. |
valueLabel | string | undefined | — | Overrides the value announced by assistive technology. |
onChange | ChangeEventHandler<HTMLDivElement, Element> | undefined | — | Standard React/HTML attribute. |
defaultValue | string | number | readonly string[] | undefined | — | Standard React/HTML attribute. |
className | string | undefined | — | Standard React/HTML attribute. |
style | CSSProperties | undefined | — | Standard React/HTML attribute. |
aria-label | string | undefined | — | Defines a string value that labels the current element. |
onClick | MouseEventHandler<HTMLDivElement> | undefined | — | Standard React/HTML attribute. |
valuenumber | undefinedNo default extracted.
Current value between 0 and `max`. Leave it undefined for an indeterminate gauge.
maxnumber | undefinedDefault: 100
Upper bound.
size"sm" | "md" | "lg" | undefinedDefault: "md"
Visual size of the gauge.
variant"primary" | "secondary" | "neutral" | "success" | "warning" | "danger" | undefinedDefault: "primary"
Tone of the indicator.
labelstring | undefinedNo default extracted.
Accessible name of the gauge. It is not rendered: a circular gauge is too small to carry a readable label, so compose it next to the component.
showValueboolean | undefinedDefault: false
Display the current value in the middle.
formatValue((value: number, max: number) => string) | undefinedNo default extracted.
Formats the readout, for example (value, max) => `${value}/${max}`.
valueLabelstring | undefinedNo default extracted.
Overrides the value announced by assistive technology.
onChangeChangeEventHandler<HTMLDivElement, Element> | undefinedNo default extracted.
Standard React/HTML attribute.
defaultValuestring | number | readonly string[] | undefinedNo default extracted.
Standard React/HTML attribute.
classNamestring | undefinedNo default extracted.
Standard React/HTML attribute.
styleCSSProperties | undefinedNo default extracted.
Standard React/HTML attribute.
aria-labelstring | undefinedNo default extracted.
Defines a string value that labels the current element.
onClickMouseEventHandler<HTMLDivElement> | undefinedNo default extracted.
Standard React/HTML attribute.
Accessibility
- Provide an accessible label and a meaningful value or busy message.