Noctis

Progress

Show how far along a task is. An accent fill grows across a recessed track — measured against a value when you know one, sweeping when you don't — and tints to the task's outcome.

Basic

A determinate bar takes a value between 0 and max (default 100). The indicator fills the track to that fraction and eases as the value changes. labels="top" lays the optional Progress.Label + Progress.Value out in a header row above the track — no wrapper needed.

Syncing
x

Labels

labels="top" (the default) stacks the caption row above the track; labels="side" flanks the track on one line. The root owns the layout, so the same parts compose either way, and a bar with no caption collapses to just the track.

Uploading
x
Uploading
x

Sizes

Two track thicknesses — md (the default) and sm, a thinner rail for dense rows and inline status. Both follow the radius knob, so a RadiusScope retunes them; for an arbitrary height, pass thickness (a number is px, a string is any CSS length).

x
x

Tone

A progress bar is a task, so its colour signals the task's outcome. neutral (the default) keeps the active accent; danger marks a failed task, warning an at-risk one, success a finished one. Tone is an explicit choice — never inferred — mirroring Meter's status vocabulary.

Uploading
x
Running low on space
x
Upload failed
x
Synced
x

Completion

When the value reaches max, every part carries data-complete and the fill plays a one-shot settle (dropped under reduced motion). "Done" isn't automatically "good", so the hue stays accent by default — signal a persistent completed state by pairing tone="success" with a "Complete" value, as here.

Exporting
x

Indeterminate

When you can't measure progress — a request in flight, a job with no known length — pass value={null}. The indicator drops its measured width and an eased sweep keeps the rail covered. The sweep respects prefers-reduced-motion, holding a steady sliver instead.

x

Formatting the value

Set max to count against a real total and format to render the value in any Intl.NumberFormat style. For a non-percentage bar, wire getAriaValueText so a screen reader announces the human value ("384 of 512 megabytes") rather than a bare percentage — the value formats and announces for the reader's locale.

Downloading
x

Controlled

Progress is display-only — it is never focusable and has no keyboard interaction (the correct ARIA outcome for a progressbar). The interactive surface is your own control; drive the value from it and the fill eases to each reading.

Buffered
x

Tone from value

Progress keeps tone explicit — map it from the value in your own code, mirroring the quota breakpoints your warnings already use, so the bar turns at the same threshold a note fires. (For a measurement with healthy zones rather than a task, reach for Meter, which derives this for you.)

Documents
x
Photos
x
System
x

Anatomy

Compose a progress bar from its parts. Progress.Root owns the value (a number, or null for indeterminate), the max/min bounds, the value format, and the shared tone/size/labels.

  • Progress.Root — the container and the progressbar. Props: value (required; null is indeterminate), max (default 100), min (default 0), format, getAriaValueText/aria-valuetext, locale, tone (default neutral), size (default md), labels (default top), thickness, plus the Base UI Progress.Root props. Name it with Progress.Label or an aria-label.
  • Progress.Track — the recessed rail. Holds a single Progress.Indicator.
  • Progress.Indicator — the fill. Base UI sizes its width to the value; the resolved tone colours it, and it eases as the value changes. An indeterminate bar sweeps it.
  • Progress.Label — the bar's visible name. Laid out by the root's labels axis.
  • Progress.Value — the formatted completion text. Pass a child function (formattedValue, value) => … to render a custom string.

Every part carries a data-slot (progress, progress-track, progress-indicator, progress-label, progress-value) for host-side styling — pair the root slot with the data-tone/data-size/data-labels axes it stamps, or with the Base UI status attributes (data-indeterminate, data-progressing, data-complete) every part carries. The bar is RTL-aware: the fill grows from the inline start and the sweep mirrors by direction. It is non-interactive by design — never focusable.

On surfaces

The same control re-tuned across the elevation scopes — the root canvas, an elevated panel, a menu, and a sunken well. It stays legible on every layer.

root
Uploading
x
elevated
Uploading
x
menu
Uploading
x
sunken
Uploading
x

Design tokens

Generated from the component's declaration — the same graph that mints the CSS, so a variable name or its resolution default can't drift. The track and fill follow the radius knob (--noctis-radius-control), and the label/value colours, track thickness, and indicator fill are all minted (matching Meter), so they're the public override seam: set one on any ancestor and every progress bar in that region retunes — e.g. .dense { --noctis-progress-track-block-size: 0.1875rem; } thins every bar (or pass thickness per instance). See Customization for the full override ladder and Tokens for the whole graph.

Token

API reference

Generated from the component's types — every prop, type, default, and description comes straight from the source. Each part gets its own table; parts that only forward to Base UI (Track, Indicator, Label, Value) list just the props they pass through. Expand a row for the full type and description.

Progress.Root

Prop

Progress.Track

Prop

Progress.Indicator

Prop

Progress.Label

Prop

Progress.Value

Prop

AttributeDescription
data-slotThe root progress element.
data-tone`neutral` | `success` | `warning` | `danger` — the task-outcome tint, stamped on the root.
data-size`sm` | `md` — the track thickness, stamped on the root.
data-labels`top` | `side` — the caption placement relative to the track, stamped on the root.
data-indeterminatePresent on every part while the value is `null` (no measurable progress).
data-progressingPresent on every part while the value is between its min and max.
data-completePresent on every part once the value reaches its max.