All components
Feedback
Progress
stable
Since 1.2
Linear and circular progress with four label placements, full-ring and half-gauge shapes, and a distinct indeterminate state.
Feedback
primitive
Display
Documented
import { Progress } from '@ivim/native/components';
When to use
Use when
A task has a measurable completion, such as an upload or an import.
A quota or capacity should be shown against its limit — use ProgressCircle.
A known task is running with unknown duration — use isIndeterminate.
Don't use when
Content is simply not ready yet and no task is running — use Spinner, which carries no task semantics.
The value is something the user sets — use Slider.
The steps are discrete and named — use Stepper.
Playground
Adjust the controls to preview live prop combinations. The code snippet updates to match the current selection.
Uploading
40%
Label placement
labelPlacement
none
right
bottom
floating
size
size
sm
md
lg
Indeterminate
isIndeterminate
<Progress labelPlacement="right" />
Example
Preview
Code
Linear
No read-out
Read-out on the right
Uploading
40%
Read-out below
Uploading
62%
Floating read-out
62%
Formatted units
Uploading
40 of 100 MB
About 20 seconds remaining
Indeterminate (no value announced)
Loading
Custom range (minValue/maxValue)
Dosage (50–200 mg)
50%
Sizes (sm, md, lg)
Circular
Full ring
25%
62%
90%
Half gauge
62%
Rich centre content
12 GB
of 20 GB
With a label
62%
Storage used
Indeterminate ownership
Indeterminate progress lives here rather than in `Spinner`. This control means “a known task is running”; `Spinner` means “content is not ready yet” and carries no task semantics. The indeterminate bar shows a partial sweep rather than animating, so it stays legible under reduced-motion preferences.
Anatomy
The parts that compose this component.
1
Track
The unfilled rail, or the ring background.
2
Fill
The completed portion.
3
Label
Task name, above the track.
4
Read-out
The value, placed right, bottom, or floating over the fill.
5
Helper text
Supporting detail beneath.
Guidelines
Do
Show the value with labelPlacement when the number itself is useful — a bare bar tells you little.
Do
Use formatValue for units people recognise ("40 of 100 MB") rather than a bare percentage.
Do
Use isIndeterminate rather than a fake creeping value when duration is genuinely unknown.
Don't
Use Progress purely for decoration — it announces as a progressbar and implies a real task.
Props
Public props for this component. Required props are marked; defaults reflect the component implementation.
value
number
Within [minValue, maxValue]. Omit for an indeterminate bar.
minValue / maxValue
number
default: 0 / 100
Range `value` is normalized against — the fill is (value − minValue) / (maxValue − minValue), clamped to 0–100%.
isIndeterminate
boolean
default: false
Unknown duration. Announces busy and publishes no value.
labelPlacement
'none' | 'right' | 'bottom' | 'floating'
default: 'none'
Where the value read-out sits.
formatValue
(value: number) => string
Formats the read-out and the announced value text.
label / helperText
ReactNode
Task name and supporting detail.
size
'sm' | 'md' | 'lg'
default: 'md'
Track thickness.
ProgressCircle: shape
'full' | 'half'
default: 'full'
Complete ring, or a half-circle gauge.
ProgressCircle: children
ReactNode
Centre content, replacing the default percentage.
color / trackColor
ThemeColor
default: 'bgBrandSolid' / 'bgTertiary'
Fill and rail colors, from the semantic token set.
aria-label
string
Accessible name when there is no visible label, or when the label is not plain text.
Deviations from Untitled UI
Where this component deliberately differs from Untitled UI's API, and why. These are kept choices, not gaps to close.
Untitled UI
`labelPosition` / `labelFormatter` / `valueFormatter`
Ours
`labelPlacement` / `formatValue`
Kept: an internally consistent pair shared by Slider, Progress, and ProgressCircle. A cross-library rename would churn three APIs for cosmetic parity.
Accessibility
Roles and screen-reader behavior this component provides, plus keyboard interactions.
•
Announces accessibilityRole="progressbar" with min, max, and now — the previous implementation had no role or value at all.
•
Indeterminate publishes no value: reporting 0 would announce "0 percent" for progress that is simply unknown. It reports busy instead.
•
Values clamp to 0–100, so an out-of-range input never announces something impossible.
•
react-native-web drops accessibilityValue, so aria-value* are emitted explicitly for the DOM.
•
The circular form is drawn with stroke-dash rather than rotation, so no animation is needed to represent a value — which matters under reduced motion.
—
Not interactive. Progress reports state; it does not accept input.
Platform & RTL
Behavior that differs across the platforms this component runs on.
Web
Emits role="progressbar" with aria-valuenow, or aria-busy when indeterminate.
iOS
VoiceOver announces the progressbar trait and its value.
Android
TalkBack announces the progressbar trait and its value.
RTL
The fill grows from the start edge, mirroring with the writing direction.
State coverage
Interaction and visual states this component supports.
base
semantic color
density
Token references
Semantic design tokens this component page exercises. Tap one to edit it live.
Related components
Components that solve adjacent problems or compose with this one.
Spinner
Activity indicator with theme color and native sizes.
Slider
Range input with one or two thumbs, supporting drag, keyboard, and assistive-technology adjustment with step snapping and value announcement.
Stepper
Vertical progress list for setup, onboarding, and multi-step form flows.
Skeleton
Animated loading placeholder with live theme token colors.