CircularProgress
Renders a circular loading indicator. Supports indeterminate (looping) and determinate (value-driven) variants. The stroke color is set via CSS currentColor; the color prop resolves to theme.palette[color].main.
Architecture: the root element is a <span> (not <svg>). This avoids a TypeScript incompatibility between SVGAttributes.height and LayoutProps.height. The internal <svg> fills the span via width/height="100%" and uses a fixed viewBox="0 0 44 44" coordinate system - the size prop scales the outer span via CSS width/height.
Examples
Default
<CircularProgress variant="indeterminate" color="primary" size={40} />
Determinate
<CircularProgress variant="determinate" color="primary" size={40} value={70} />
Spinning Determinate
25%
50%
75%
<Flex flexDirection="row" gap={4} alignItems="center">
{([25, 50, 75] as const).map((value) => (
<Flex key={value} flexDirection="column" alignItems="center" gap={1}>
<CircularProgress variant="determinate" value={value} spinning size={48} />
<Typography variant="caption" color="secondary" m={0}>
{value}%
</Typography>
</Flex>
))}
</Flex>
Colors
primary
secondary
success
error
info
warning
<Flex flexDirection="column" gap={3}>
{(['primary', 'secondary', 'success', 'error', 'info', 'warning'] as const).map((color) => (
<Flex key={color} flexDirection="row" gap={2} alignItems="center">
<Typography variant="caption" color="secondary" width="6rem" flexShrink={0} m={0}>
{color}
</Typography>
<CircularProgress showTrack color={color} size={32} />
<CircularProgress showTrack variant="determinate" value={65} color={color} size={32} />
</Flex>
))}
</Flex>
Sizes
16px
24px
40px
64px
80px
<Flex flexDirection="row" gap={3} alignItems="end" flexWrap="wrap">
{([16, 24, 40, 64, 80] as const).map((size) => (
<Flex key={size} flexDirection="column" alignItems="center" gap={1}>
<CircularProgress size={size} />
<Typography variant="caption" color="secondary" m={0}>
{size}px
</Typography>
</Flex>
))}
</Flex>
Thickness
1
2
3.6
6
10
<Flex flexDirection="row" gap={3} alignItems="center" flexWrap="wrap">
{([1, 2, 3.6, 6, 10] as const).map((thickness) => (
<Flex key={thickness} flexDirection="column" alignItems="center" gap={1}>
<CircularProgress thickness={thickness} size={48} />
<Typography variant="caption" color="secondary" m={0}>
{thickness}
</Typography>
</Flex>
))}
</Flex>
Show Track
indeterminate
determinate 65%
<Flex flexDirection="row" gap={4} alignItems="center" flexWrap="wrap">
<Flex flexDirection="column" alignItems="center" gap={1}>
<CircularProgress showTrack size={48} />
<Typography variant="caption" color="secondary" m={0}>
indeterminate
</Typography>
</Flex>
<Flex flexDirection="column" alignItems="center" gap={1}>
<CircularProgress variant="determinate" value={65} showTrack size={48} />
<Typography variant="caption" color="secondary" m={0}>
determinate 65%
</Typography>
</Flex>
</Flex>
Easing
linear
ease
ease-in
ease-out
ease-in-out
<Flex flexDirection="row" gap={4} alignItems="center" flexWrap="wrap">
{(['linear', 'ease', 'ease-in', 'ease-out', 'ease-in-out'] as const).map((easing) => (
<Flex key={easing} flexDirection="column" alignItems="center" gap={1}>
<CircularProgress easing={easing} size={48} />
<Typography variant="caption" color="secondary" m={0}>
{easing}
</Typography>
</Flex>
))}
</Flex>
Custom Range
3 of 10
120 of 200
7 of 5-15
<Flex flexDirection="column" gap={3}>
{(
[
{ value: 3, min: 0, max: 10, label: '3 of 10' },
{ value: 120, min: 0, max: 200, label: '120 of 200' },
{ value: 7, min: 5, max: 15, label: '7 of 5-15' },
] as const
).map(({ value, min, max, label }) => (
<Flex key={label} flexDirection="row" gap={2} alignItems="center">
<CircularProgress
variant="determinate"
value={value}
min={min}
max={max}
showTrack
size={48}
/>
<Typography variant="caption" color="secondary" m={0}>
{label}
</Typography>
</Flex>
))}
</Flex>
Spinning With Track
25%
50%
75%
90%
<Flex flexDirection="row" gap={4} alignItems="center" flexWrap="wrap">
{([25, 50, 75, 90] as const).map((value) => (
<Flex key={value} flexDirection="column" alignItems="center" gap={1}>
<CircularProgress
variant="determinate"
value={value}
spinning
showTrack
size={56}
thickness={5}
/>
<Typography variant="caption" color="secondary" m={0}>
{value}%
</Typography>
</Flex>
))}
</Flex>
Disable Shrink
default
disableShrink
<Flex flexDirection="row" gap={4} alignItems="center">
<Flex flexDirection="column" alignItems="center" gap={1}>
<CircularProgress />
<Typography variant="caption" color="secondary" m={0}>
default
</Typography>
</Flex>
<Flex flexDirection="column" alignItems="center" gap={1}>
<CircularProgress disableShrink />
<Typography variant="caption" color="secondary" m={0}>
disableShrink
</Typography>
</Flex>
</Flex>