Skip to content

Progress Bar

FeedbackSince 0.2.0
import { ProgressBar } from '@absoluteui/components/progress-bar';
import '@absoluteui/components/progress-bar/style.css';

Using Angular? See Progress Bar for Angular.

A determinate or indeterminate progress indicator with role="progressbar". It provides:

  • a visible label that is the accessible name;
  • localized percentage value text (aria-valuetext), or custom value text;
  • optional help text;
  • tones (success, warning, error) that add a labelled icon, so meaning never depends on color alone;
  • an optional one-time completion announcement.
  • Operations with measurable progress (uploads, imports, multi-step processing).
  • Long operations of unknown duration where a labelled indeterminate bar is clearer than a spinner.
  • Short waits under about a second: use nothing, or a delayed Spinner.
  • Showing a static quantity or capacity (disk usage, scores): use a meter.
  • Placeholder layout while content loads: use Skeleton.
import { ProgressBar } from '@absoluteui/components/progress-bar';
const host = document.querySelector<HTMLElement>('#upload');
if (host) {
const bar = ProgressBar.create(host, { label: 'Uploading report.pdf', value: 0 });
const onProgress = (loaded: number, total: number): void => {
bar.setValue((loaded / total) * 100);
if (loaded >= total) bar.update({ tone: 'success' });
};
onProgress(5, 10);
}
import { ProgressBar } from '@absoluteui/components/progress-bar';
const host = document.querySelector<HTMLElement>('#import');
if (host) {
const bar = ProgressBar.create(host, { label: 'Importing contacts', value: null, description: 'Preparing file' });
bar.update({ max: 250, value: 40, description: 'Processing rows', valueText: (value, max) => `${String(value)} of ${String(max)} rows` });
}
import { ProgressBar } from '@absoluteui/components/progress-bar';
import '@absoluteui/components/progress-bar/style.css';
const host = document.querySelector<HTMLElement>('#import');
if (host) {
const bar = ProgressBar.create(host, { label: 'Importing contacts', value: null });
bar.update({ max: 250, value: 40, valueText: (value, max) => `${String(value)} of ${String(max)} rows` });
}
import { ProgressBar } from '@absoluteui/components/progress-bar';
const host = document.createElement('div');
document.body.append(host);
const bar = ProgressBar.create(host, { label: 'Uploading report.pdf', value: 0 });
bar.setValue(60);
<div class="aui-progress-bar aui-progress-bar--{tone} [aui-progress-bar--indeterminate]">
<div class="aui-progress-bar__header">
<span class="aui-progress-bar__label" id="L">label</span>
<svg class="aui-icon aui-progress-bar__icon" role="img" aria-label="Success"></svg> (non-default tones)
<span class="aui-progress-bar__value" aria-hidden="true">50%</span>
</div>
<div class="aui-progress-bar__track" role="progressbar" aria-labelledby="L" aria-describedby="D"
aria-valuemin="0" aria-valuemax="100" aria-valuenow="50" aria-valuetext="50%">
<div class="aui-progress-bar__fill"></div> (inline size from --aui-progress)
</div>
<div class="aui-progress-bar__description" id="D">help text</div>
</div>
ProgressBar.create(host: HTMLElement, options: ProgressBarOptions): ProgressBar

Global configuration key: progressBar (see Configuration).

Option Type Default Description
label string Visible label and accessible name (aria-labelledby). Required.
value number | null "null" Current value, clamped to [min, max]. null renders an indeterminate bar without aria-valuenow.
min number 0 Minimum value.
max number 100 Maximum value; must be greater than min.
valueText (value: number, max: number) => string Custom value text for aria-valuetext and the visible value. Default: localized percentage.
description string Help text referenced by aria-describedby.
tone 'default' | 'success' | 'warning' | 'error' "default" Semantic tone; non-default tones add a labelled icon.
icons Partial<{ success: IconRef; warning: IconRef; error: IconRef }> Icon slot overrides.
showValue boolean true Render the value text next to the label. Globally configurable.
announceComplete boolean true Announce “{label} complete” politely once when the value reaches max. Globally configurable.
locale string "en-US" Percentage formatting and message locale. Globally configurable. Inherited from common configuration.
Property Type Description
host HTMLElement The host element.
track HTMLDivElement The role=“progressbar” element.
value number | null Current clamped value, or null when indeterminate.
indeterminate boolean Whether the value is null.
Method Description
setValue(value: number | null): void Set the value (null for indeterminate).
update(options: Partial<ProgressBarOptions>): void Merge and apply options.
destroy(): void Remove rendering and config subscriptions.

All rules live in the aui.components cascade layer, so application styles override them without specificity battles.

Class Purpose
aui-progress-bar Host.
aui-progress-bar--default | --success | --warning | --error Tone modifiers.
aui-progress-bar--indeterminate Value is null.
aui-progress-bar__header Label, tone icon, and value row.
aui-progress-bar__label Visible label.
aui-progress-bar__icon Tone icon (role=“img” with a localized label).
aui-progress-bar__value Visible value text (aria-hidden; duplicated in aria-valuetext).
aui-progress-bar__track role=“progressbar” track.
aui-progress-bar__fill Fill; inline size from –aui-progress.
aui-progress-bar__description Help text.
Slot Default icon
success check-circle
warning alert-triangle
error alert-circle

Tokens this stylesheet reads (verified in CI). Override them in a theme or with the Theme Designer.

--aui-border-width | --aui-color-border-strong | --aui-color-error-fg | --aui-color-primary | --aui-color-success-fg | --aui-color-surface-sunken | --aui-color-text | --aui-color-text-muted | --aui-color-warning-fg | --aui-duration-fast | --aui-easing-standard | --aui-font-family-sans | --aui-font-size-sm | --aui-font-weight-medium | --aui-icon-size-sm | --aui-line-height-tight | --aui-progress-height | --aui-radius-pill | --aui-space-1 | --aui-space-2

type ProgressBarTone = 'default' | 'success' | 'warning' | 'error';
interface ProgressBarIcons { success: IconRef; warning: IconRef; error: IconRef }
interface ProgressBarConfig { showValue: boolean; announceComplete: boolean }
interface ProgressBarOptions extends Partial<ProgressBarConfig> {
label: string;
value?: number | null;
min?: number;
max?: number;
valueText?: (value: number, max: number) => string;
description?: string;
tone?: ProgressBarTone;
locale?: string;
icons?: Partial<ProgressBarIcons>;
}

Pattern: WAI-ARIA progressbar role (ARIA 1.2) with a visible label.

Key Context Action
None Any Not focusable; progress is conveyed through the progressbar role and optional live announcement.
Element Role
track progressbar
tone icon img (localized label: Success, Warning, Error)
Attribute Element Value
aria-labelledby track id of the visible label
aria-describedby track id of the description (when provided)
aria-valuemin / aria-valuemax track min / max
aria-valuenow track Clamped value; absent when indeterminate
aria-valuetext track Localized percentage or valueText(); absent when indeterminate
aria-hidden visible value text “true” (duplicated in aria-valuetext)

Not focusable. Focus is never moved by value changes.

Criterion Level Note
1.3.1 Info and Relationships A
1.4.1 Use of Color A
1.4.11 Non-text Contrast AA
2.3.3 Animation from Interactions AAA
4.1.2 Name, Role, Value A
4.1.3 Status Messages AA

Automated test results: Accessibility and compliance.

  • Value changes are not announced continuously; completion is announced once through the shared polite live region (announceComplete).
  • Non-default tones include a labelled icon so meaning never depends on color alone (1.4.1).
  • The indeterminate sweep is replaced by a static striped bar under prefers-reduced-motion or animation: none.
  • Manual screen-reader verification (NVDA, JAWS, VoiceOver) is pending.

indeterminate (value: null), determinate, complete (value === max), and the tone (default, success, warning, error).

From Trigger To
indeterminate setValue(n) determinate (aria-valuenow added)
determinate setValue(null) indeterminate (aria-valuenow and aria-valuetext removed)
determinate (< max) setValue(max) complete; announces “{label} complete” once when announceComplete
complete setValue(< max) then setValue(max) complete again; announces again
any update({ tone }) same value, new tone icon and fill color
  • Value changes are not announced continuously (that would be noisy). Completion is announced once through the shared polite live region.
  • Tones add a labelled icon so success or failure is not conveyed by color alone (WCAG 1.4.1).
  • The indeterminate sweep is replaced by a static striped bar under prefers-reduced-motion: reduce or animation: 'none'.
  • Manual screen-reader verification is pending.

Fills the inline size of its container. The label wraps; the value text stays on one line at the inline end.

Logical properties throughout: the fill grows from the inline start, the indeterminate sweep moves toward the inline end, and the value sits at the inline end.

The track uses color-surface-sunken with a color-border-strong boundary; the fill uses color-primary or the tone foreground token. Forced-colors mode uses Highlight for the fill and CanvasText for the boundary.

configureAbsoluteUI({ components: { progressBar: { showValue: false, announceComplete: false } } });

Changes apply to existing instances immediately.

Instance options override global and theme defaults. All options are dynamic.

icons.success (default check-circle), icons.warning (default alert-triangle), and icons.error (default alert-circle).

All text uses textContent; valueText results are rendered as text. The fill width is written as the --aui-progress custom property through style.setProperty (CSSOM, CSP-safe); no style attribute strings are generated.

No persistence, network access, or telemetry.

No DOM listeners; one configuration subscription. setValue updates attributes, text, and one custom property. Target: under 1 ms per setValue in headless Chromium (not yet covered by the e2e performance suite).

One bar per operation. Frequent updates (every animation frame) are supported.

  • Values outside [min, max] are clamped; value returns the clamped value.
  • The percentage is relative to the range: min: 50, max: 150, value: 100 reads “50%”.
  • Locales format the percentage natively, for example de-DE renders “50 %” (with a no-break space).
  • A bar created at max does not announce; repeated setValue(max) announces only once.
Code Category Cause
PROGRESS_BAR_OPTIONS configuration Missing label, non-finite min/max/value, max <= min, invalid tone, or non-function valueText.
CFG_INVALID_VALUE / CFG_UNKNOWN_OPTION configuration Invalid or unknown configuration.

A failed construction leaves the host untouched.

  • Completion is announced once per transition to max.
  • Values are clamped rather than rejected.
  • Manual screen-reader verification is pending.
  • Buffered or secondary progress values.
  • Circular (ring) progress.
  • HTML in the label, value text, or description.