Progress Ring
Progress rings provide users with visual feedback about the status of ongoing processes through a circular progress indicator. This component displays both determinate progress with specific percentages and indeterminate loading states.
import {ProgressRing} from "@qualcomm-ui/react/progress-ring"Overview
The progress ring can be in one of two states:
- indeterminate: the default state.
- determinate: assumed when the value prop is passed.
Indeterminate progress rings keep users informed that work is happening when timeframes are unknown.
Examples
Simple
For most use cases, you can use the simple ProgressRing component.
<ProgressRing />
Composite
Build with the composite API for granular control. This API requires you to provide each subcomponent, but gives you full control over the structure and layout.
import type {ReactElement} from "react"
import {ProgressRing} from "@qualcomm-ui/react/progress-ring"
export function ProgressRingCompositeDemo(): ReactElement {
return (
<ProgressRing.Root size="lg">
<ProgressRing.CircleContainer>
<ProgressRing.Circle>
<ProgressRing.Track />
<ProgressRing.Bar />
</ProgressRing.Circle>
</ProgressRing.CircleContainer>
<ProgressRing.Label>Loading...</ProgressRing.Label>
</ProgressRing.Root>
)
}Value
When the value prop is set, the filled portion of the circle will represent the total percent relative to max and min. This is referred to as the "determinate" state.
<ProgressRing
size="lg"
value={value}
valueText={(api) => `${api.valuePercent}%`}
/>
Value Text
Display the value text by passing a value to the valueText prop. The value text only shows when the size is lg or xl.
<ProgressRing
size="lg"
value={value}
valueText={(api) => `${api.valuePercent}%`}
/>
Sizes
Use the size prop to change the size of the circle.
import {type ReactElement, useEffect, useState} from "react"
import {ProgressRing} from "@qualcomm-ui/react/progress-ring"
export function ProgressRingSizesDemo(): ReactElement {
const [value, setValue] = useState<number>(0)
useEffect(() => {
function increment() {
setValue((prevValue) => {
if (prevValue === 100) {
return 0
}
return prevValue + 10
})
}
const timer = setInterval(increment, 1000)
return () => clearInterval(timer)
}, [])
return (
<div className="flex items-center gap-4">
<div className="grid grid-cols-3 items-center justify-items-center gap-x-8 gap-y-4">
<div className="font-heading-xs text-neutral-primary">xxs</div>
<ProgressRing size="xxs" value={value} />
<ProgressRing size="xxs" />
<div className="font-heading-xs text-neutral-primary">xs</div>
<ProgressRing size="xs" value={value} />
<ProgressRing size="xs" />
<div className="font-heading-xs text-neutral-primary">sm</div>
<ProgressRing size="sm" value={value} />
<ProgressRing size="sm" />
<div className="font-heading-xs text-neutral-primary">md</div>
<ProgressRing size="md" value={value} />
<ProgressRing size="md" />
<div className="font-heading-xs text-neutral-primary">lg</div>
<ProgressRing
size="lg"
value={value}
valueText={(api) => `${api.valuePercent}%`}
/>
<ProgressRing size="lg" />
<div className="font-heading-xs text-neutral-primary">xl</div>
<ProgressRing
size="xl"
value={value}
valueText={(api) => `${api.valuePercent}%`}
/>
<ProgressRing size="xl" />
</div>
</div>
)
}Thickness
Use the thickness prop to change the pixel width of the track and bar.
<ProgressRing className="py-2" size="lg" thickness={8} />
Disabled
Use the disabled prop to indicate that the progress indicator is inactive.
<ProgressRing disabled label="Indeterminate" size="lg" />
<ProgressRing
disabled
label="Determinate"
size="lg"
value={64}
valueText="64%"
/>
Shortcuts
The ProgressRing.Circle component automatically renders the track and bar components when child. The following two examples are
<ProgressRing.Circle />Accessibility
- When the value is supplied, the component automatically provides the corresponding
aria-value*attributes to the element. - The progress element is automatically marked with
role="progressbar". - The label is automatically associated with the progress bar. If you omit the label property, the
aria-labelof the progress element defaults to the value when determinate, and "Loading" when indeterminate.
Explorer
Component Anatomy
Hover to highlight, click to view API
API
<ProgressRing>
The ProgressRing component extends the ProgressRing.Root with the following props:
ProgressApi
This API is accessible in JSX via the <ProgressRing.Context> component:
<ProgressRing.Context>
{(api: ProgressApi) => {
return <>{/*...*/}</>
}}
</ProgressRing.Context>booleannumbernumber(
value: number,
) => void
| 'indeterminate'
| 'complete'
| 'loading'
value.numbernumbermin
and max values.Composite API
<ProgressRing.Root>
<div>
element by default.number'ltr' | 'rtl'
booleantrue, the progress is disabled.| 'primary'
| 'neutral'
Partial<{
errorText: string
hint: string
label: string
progress: string
}>
booleantrue, the progress is marked as invalid.numbernumber(
value: number | undefined,
) => void
| ReactElement
| ((
props: object,
) => ReactElement)
| 'xxs'
| 'xs'
| 'sm'
| 'md'
| 'lg'
| 'xl'
| number
| string
| number
The default value varies based on the size of the progress circle.
numberclassName'qui-progress-ring__root'data-disableddata-invaliddata-maxnumberdata-progress-part'root'data-size| 'xxs'
| 'xs'
| 'sm'
| 'md'
| 'lg'
| 'xl'
| number
data-state| 'indeterminate'
| 'complete'
| 'loading'
data-valuenumberstyle<ProgressRing.Label>
<label> element by
default.string| ReactElement
| ((
props: object,
) => ReactElement)
className'qui-progress-ring__label'data-progress-part'label'<ProgressRing.ValueText>
lg or
xl. Renders a <div> element by default.| ReactElement
| ((
props: object,
) => ReactElement)
className'qui-progress-ring__value-text'data-invaliddata-progress-part'value-text'hiddenboolean<ProgressRing.ErrorText>
<div> element by default.string| ReactElement
| ((
props: object,
) => ReactElement)
className'qui-progress-ring__error-text'data-progress-part'error-text'hiddenboolean<ProgressRing.CircleContainer>
<div> element
by default.| ReactElement
| ((
props: object,
) => ReactElement)
className'qui-progress-ring__circle-container'data-progress-part'circle-container'<ProgressRing.Circle>
<svg> element.stringclassName'qui-progress-ring__circle'data-disableddata-emphasis| 'primary'
| 'neutral'
data-progress-part'circle'data-size| 'xxs'
| 'xs'
| 'sm'
| 'md'
| 'lg'
| 'xl'
| number
data-state| 'indeterminate'
| 'complete'
| 'loading'
style<ProgressRing.Track>
<circle> element.className'qui-progress-ring__track'data-disableddata-progress-part'circle-track'data-size| 'xxs'
| 'xs'
| 'sm'
| 'md'
| 'lg'
| 'xl'
| number
data-state| 'indeterminate'
| 'complete'
| 'loading'
<ProgressRing.Bar>
<circle> element.className'qui-progress-ring__bar'data-disableddata-emphasis| 'primary'
| 'neutral'
data-invaliddata-maxnumberdata-progress-part'circle-bar'data-size| 'xxs'
| 'xs'
| 'sm'
| 'md'
| 'lg'
| 'xl'
| number
data-state| 'indeterminate'
| 'complete'
| 'loading'
style