ProgressIndicator shows a determinate value as a filled portion of a horizontal track. Reach for it when the amount of work completed is known and can be updated accurately, and when horizontal space is the clearest way to express it — a download in a list row, a step counter across a flow, an upload under a thumbnail.progressbar semantics. Use IndeterminateLoader when completion cannot be estimated, ProgressRing or CircularProgressBar when a circular form fits the layout better, and SliderBar or IsolatedControl when the user is meant to change the value.import { ProgressIndicator } from '@wearables-ui-toolkit/mrbd';
type Props = {
bytesReceived: number;
bytesTotal: number;
};
export function DownloadRow({ bytesReceived, bytesTotal }: Props) {
return (
<div className="download-row">
<span className="uit-text-body2">Downloading update</span>
<ProgressIndicator
value={bytesReceived}
maximumValue={bytesTotal}
animated
aria-label="Downloading update"
/>
</div>
);
}
.download-row {
display: flex;
flex-direction: column;
gap: var(--uit-spacing-xsmall);
padding: var(--uit-spacing-medium);
}
import {
ProgressIndicator,
ProgressIndicatorSize,
TextView,
TextStyle,
} from '@wearables-ui-toolkit/mrbd';
type Episode = {
id: string;
title: string;
secondsPlayed: number;
secondsTotal: number;
};
export function EpisodeRow({ episode }: { episode: Episode }) {
return (
<div className="episode-row">
<TextView textStyle={TextStyle.BODY2}>{episode.title}</TextView>
<ProgressIndicator
size={ProgressIndicatorSize.THIN}
value={episode.secondsPlayed}
maximumValue={episode.secondsTotal}
isActive={episode.secondsPlayed > 0}
announceUpdatesForAccessibility={false}
aria-label={`${episode.title} playback position`}
/>
</div>
);
}
.episode-row {
display: flex;
flex-direction: column;
gap: var(--uit-spacing-2xs);
}
ProgressIndicatorProps, which extends HTMLAttributes<HTMLDivElement>.| Prop | Type | Default | Description |
|---|---|---|---|
value | number | 0 | Current value. Clamped to the range before it is drawn and reported. |
minimumValue | number | 0 | Low end of the range, reported as aria-valuemin. |
maximumValue | number | 1 | High end of the range, reported as aria-valuemax. |
size | ProgressIndicatorSize | ProgressIndicatorSize.DEFAULT | Bar thickness variant. |
isActive | boolean | true | Draws the fill in the active color when true, the idle color when false. |
animated | boolean | false | Tween value and fill-color changes instead of snapping. Applies to every change while set. |
announceUpdatesForAccessibility | boolean | true | Publish the rounded percentage into a polite live region so screen readers narrate each change. Set false to keep the indicator silent. |
aria-label | string | — | Appended after the percentage in the accessible name. Blank or whitespace-only labels are ignored. |
className | string | '' | Added to the root element. |
style | CSSProperties | {} | Merged onto the root element. |
aria-* attribute you pass — aria-describedby and aria-labelledby, for example — is applied to the inner progressbar element, where it can take effect; every other DOM prop, including data-*, lands on the root. The component writes role, aria-valuenow, aria-valuemin, and aria-valuemax on that inner element last, so values you pass for those four are overwritten.ProgressIndicatorSize| Member | Description |
|---|---|
DEFAULT | Standard thickness, suitable for most layouts. |
THIN | Reduced thickness for dense rows and compact overlays. |
[minimumValue, maximumValue], so a stale or out-of-range value never overdraws the track. Pass the range that matches your source of truth — bytes, seconds, steps — rather than converting to a fraction yourself.minimumValue and maximumValue are equal the indicator reports 100%, which keeps a zero-length range from reading as “no progress”.isActive changes color only. Because the bar does not expand on state change, it keeps a constant thickness in both states, so an active/inactive flip never shifts surrounding layout.animated unset, value and color changes apply immediately. Setting it applies a sampled spring transition to the fill width and a container-state transition to the fill color. It is a persistent declarative prop backed by CSS transitions, so it affects every subsequent change while it is set; to animate only some updates, toggle it around the update.usePrefersReducedMotion and drop animated when the user has asked for less motion.--uit-color-background-track. The fill uses --uit-color-control-active when active and --uit-color-control-idle when inactive, so the bar stays legible on the additive-light display without any color work from you.minimumValue renders an empty track rather than removing the bar, so a row’s height does not change when progress starts at zero.role="progressbar" carrying aria-valuenow, aria-valuemin, and aria-valuemax from the clamped value and the range, so aria-valuenow is reported in your own units rather than as a percentage. The drawn bar inside it is hidden from assistive technology, so the component contributes exactly one progressbar to the accessibility tree.aria-label when you supply one — 50%, Downloading update. Give it a label that names the work, not the widget. A label that is empty or only whitespace is ignored and the bare percentage is used.progressbar element so the change is reliably picked up. Turn announceUpdatesForAccessibility off when several indicators share a screen, when the value updates many times per second, or when a nearby status line already narrates the same progress.aria-labelledby when the naming text already exists on screen, and aria-describedby for supplementary detail; both are forwarded to the progressbar element.THIN inside dense rows where a full-weight bar would crowd the content.minimumValue and maximumValue in the units your data already uses and let the component derive the percentage.animated on for a value that already arrives smoothly — the transition will lag behind the data.isActive for supported appearance changes. Internal track and fill elements are not supported customization surfaces.