ProgressCircle
A circular progress indicator that shows determinate or indeterminate progress.
Usage
import { ProgressCircle } from '@lenso/ui';"use client";
import { ProgressCircle } from "@lenso/ui";
export function Basic() { return ( <ProgressCircle aria-label="Loading" value={60}> <ProgressCircle.Track> <ProgressCircle.TrackCircle /> <ProgressCircle.FillCircle /> </ProgressCircle.Track> </ProgressCircle> );}Local adaptation source above. Derived from HeroUI v3.2.6 source.
Anatomy
import { ProgressCircle } from '@lenso/ui';
export default () => ( <ProgressCircle aria-label="Loading" value={60}> <ProgressCircle.Track> <ProgressCircle.TrackCircle /> <ProgressCircle.FillCircle /> </ProgressCircle.Track> </ProgressCircle>);Examples
Sizes
"use client";// Adapted from HeroUI v3.2.6 (Apache-2.0).import { ProgressCircle } from "@lenso/ui";import * as stylex from "@stylexjs/stylex";const styles = stylex.create({ row: { display: "flex", alignItems: "center", gap: 24 } });export function Sizes() { return ( <div {...stylex.props(styles.row)}> {( [ ["sm", 40], ["md", 60], ["lg", 80], ] as const ).map(([size, value]) => ( <ProgressCircle key={size} aria-label="Loading" size={size} value={value}> <ProgressCircle.Track> <ProgressCircle.TrackCircle /> <ProgressCircle.FillCircle /> </ProgressCircle.Track> </ProgressCircle> ))} </div> );}export default Sizes;Local adaptation source above. Derived from HeroUI v3.2.6 source.
Colors
"use client";// Adapted from HeroUI v3.2.6 (Apache-2.0).import { ProgressCircle } from "@lenso/ui";import * as stylex from "@stylexjs/stylex";const styles = stylex.create({ row: { display: "flex", alignItems: "center", gap: 24 } });export function Colors() { return ( <div {...stylex.props(styles.row)}> {(["default", "accent", "success", "warning", "danger"] as const).map((color) => ( <ProgressCircle key={color} aria-label={color} color={color} value={60}> <ProgressCircle.Track> <ProgressCircle.TrackCircle /> <ProgressCircle.FillCircle /> </ProgressCircle.Track> </ProgressCircle> ))} </div> );}export default Colors;Local adaptation source above. Derived from HeroUI v3.2.6 source.
Indeterminate
Use isIndeterminate when progress cannot be determined.
"use client";// Adapted from HeroUI v3.2.6 (Apache-2.0); null is Base UI's indeterminate value.import { ProgressCircle } from "@lenso/ui";export function Indeterminate() { return ( <ProgressCircle aria-label="Loading" value={null}> <ProgressCircle.Track> <ProgressCircle.TrackCircle /> <ProgressCircle.FillCircle /> </ProgressCircle.Track> </ProgressCircle> );}export default Indeterminate;Local adaptation source above. Derived from HeroUI v3.2.6 source.
With Label
"use client";// Adapted from HeroUI v3.2.6 (Apache-2.0); the label belongs to the progress context.import { ProgressCircle } from "@lenso/ui";import * as stylex from "@stylexjs/stylex";const styles = stylex.create({ row: { display: "flex", alignItems: "center", gap: 12 } });export function WithLabel() { return ( <ProgressCircle xstyle={styles.row} value={75}> <ProgressCircle.Track> <ProgressCircle.TrackCircle /> <ProgressCircle.FillCircle /> </ProgressCircle.Track> <ProgressCircle.Label>75% Complete</ProgressCircle.Label> </ProgressCircle> );}export default WithLabel;Local adaptation source above. Derived from HeroUI v3.2.6 source.
Custom SVG Props
Since each part is a composable component, you can override SVG attributes like strokeWidth, r, cx, cy, and viewBox directly.
"use client";// Adapted from HeroUI v3.2.6 (Apache-2.0).import { ProgressCircle } from "@lenso/ui";import * as stylex from "@stylexjs/stylex";const styles = stylex.create({ row: { display: "flex", alignItems: "flex-end", gap: 24 } });export function CustomSvg() { return ( <div {...stylex.props(styles.row)}> <ProgressCircle aria-label="Thin circle" value={60}> <ProgressCircle.Track strokeWidth={2} viewBox="0 0 36 36"> <ProgressCircle.TrackCircle cx={18} cy={18} r={17} strokeWidth={2} /> <ProgressCircle.FillCircle cx={18} cy={18} r={17} strokeWidth={2} /> </ProgressCircle.Track> </ProgressCircle> <ProgressCircle aria-label="Default circle" value={60}> <ProgressCircle.Track> <ProgressCircle.TrackCircle /> <ProgressCircle.FillCircle /> </ProgressCircle.Track> </ProgressCircle> <ProgressCircle aria-label="Thick circle" value={60}> <ProgressCircle.Track strokeWidth={6} viewBox="0 0 36 36"> <ProgressCircle.TrackCircle cx={18} cy={18} r={15} strokeWidth={6} /> <ProgressCircle.FillCircle cx={18} cy={18} r={15} strokeWidth={6} /> </ProgressCircle.Track> </ProgressCircle> </div> );}export default CustomSvg;Local adaptation source above. Derived from HeroUI v3.2.6 source.
Customization
Tailwind CSS
"use client";// Adapted from HeroUI v3.2.6 (Apache-2.0).import { ProgressCircle } from "@lenso/ui";import * as stylex from "@stylexjs/stylex";const styles = stylex.create({ track: { width: 56, height: 56 }, background: { stroke: "light-dark(oklch(92.2% 0 0), oklch(26.9% 0 0))" }, fill: { stroke: "light-dark(oklch(37.1% 0 0), oklch(87% 0 0))" },});export function CustomStyles() { return ( <ProgressCircle aria-label="Sync progress" value={68}> <ProgressCircle.Track xstyle={styles.track}> <ProgressCircle.TrackCircle xstyle={styles.background} /> <ProgressCircle.FillCircle xstyle={styles.fill} strokeLinecap="round" /> </ProgressCircle.Track> </ProgressCircle> );}export default CustomStyles;Local adaptation source above. Derived from HeroUI v3.2.6 source.
Global CSS
To customize the ProgressCircle component classes, you can use the @layer components directive.
Learn more.
@layer components { .progress-circle { @apply inline-flex; }
.progress-circle__track { @apply size-12; }
.progress-circle__fill-circle { stroke: purple; }}Styling Reference
HeroUI follows the BEM methodology to ensure component variants and states are reusable and easy to customize.
CSS Classes
The ProgressCircle component uses these CSS classes (View source styles):
Base & Element Classes [!toc]
.progress-circle- Base container.progress-circle__track- SVG element.progress-circle__track-circle- Background circle.progress-circle__fill-circle- Progress arc
Size Classes [!toc]
.progress-circle--sm- Small size variant.progress-circle--md- Medium size variant (default).progress-circle--lg- Large size variant
Color Classes [!toc]
.progress-circle--default- Default color variant.progress-circle--accent- Accent color variant.progress-circle--success- Success color variant.progress-circle--warning- Warning color variant.progress-circle--danger- Danger color variant
API Reference
ProgressCircle
Inherits from React Aria ProgressBar.
| Prop | Type | Default | Description |
|---|---|---|---|
value | number | 0 | The current value |
minValue | number | 0 | The minimum value |
maxValue | number | 100 | The maximum value |
isIndeterminate | boolean | false | Whether progress is indeterminate |
size | "sm" | "md" | "lg" | "md" | Size of the circle |
color | "default" | "accent" | "success" | "warning" | "danger" | "accent" | Color of the progress arc |
formatOptions | Intl.NumberFormatOptions | {style: 'percent'} | Number format for the value display |
children | ReactNode | (values: ProgressBarRenderProps) => ReactNode | - | Content or render prop |
Render Props
When using the render prop pattern, these values are provided:
| Prop | Type | Description |
|---|---|---|
percentage | number | The percentage of the progress (0-100) |
valueText | string | The formatted value text |
isIndeterminate | boolean | Whether progress is indeterminate |