What it is
A ProgressBar is a horizontal track that fills to show completion. It has two distinct jobs bundled into one component, switched by itsvariant prop: determinate, where a real 0–100
value fills the bar to an exact point (“how much longer”), and indeterminate, where the bar
animates with no real value behind it (“still working, duration unknown”).
That determinate/indeterminate split is what separates it from the other two loading primitives
in this category. A Skeleton promises a
shape, not a percentage. A Spinner is a
compact, always-indeterminate mark that fits inline rather than a full-width track. ProgressBar
is the only one of the three that can report a real, measurable number.
Live example
Exports
Verified directly fromProgress/LinearProgress.tsx, which adds nothing to the interface it
wraps — no per-component prop emitter exists yet for this concept, so this table is
hand-confirmed rather than generated.
Vocabulary
Choose ProgressBar when
- The process has a real, trackable length, and you can report a percentage as it advances.
- Or: something is running with no known duration, and a full-width horizontal indicator fits the layout better than a compact circular one.
Choose something else when
Anatomy
Variants, sizes, and states
Two demonstrated variants —determinate and indeterminate — and two named colors —
primary (green) and secondary, which resolves to the dedicated progress-bar-secondary
token. error, info, success, and warning are accepted by the type but not confirmed to
route through a Titan-named token the way primary/secondary do.
No size prop. Track height comes entirely from the progress-track-height token, uniform
across every use — there is no small/medium distinction the way Button or TextField have one.
Edge and failure states
Tokens
Verified directly fromProgress.overrides.ts — no per-component token emitter exists yet for
this concept, so this table is hand-confirmed rather than generated.
Composition
No Titan component in this codebase composesLinearProgress internally — it was not found
inside any other component’s source during this pass. Its own stories compose it directly with
Box for width and, in one case, Typography for a value label; both are call-site patterns,
not something the component provides.
Content
A ProgressBar carries no text of its own. If a percentage or a status line accompanies it, it is separate content placed beside the bar — write it the way any other short status line is written, stating what’s in progress, not restating “loading.”Accessibility
Rendersrole="progressbar" unconditionally, confirmed directly in the underlying
component’s source. In determinate mode it also sets aria-valuenow, aria-valuemin (0),
and aria-valuemax (100) from the real value — confirmed in the same source. In
indeterminate mode none of the three aria-value* attributes are set, which is the correct
behavior for a progressbar with no real value to report.
No accessible name is set by the component itself. A ProgressBar describing a specific
region’s loading state needs an aria-label or an aria-describedby pointing at it — not
supplied automatically, and not verified anywhere in Titan source as a pattern any component
uses.
Constraints
Known issues
ProgressBar: open issues
Divergences, open decisions, and undocumented gaps for ProgressBar.
Why it works this way
Determinate and indeterminate are one component because they are the same visual object at different levels of information. Both are a horizontal track; the only difference is whether something outside the component can say how full it should be. Splitting them into two components would duplicate the track, the height token, and the color mapping for a difference that is really just “isvalue meaningful right now.”
The green default is inherited, not chosen for this purpose. Nothing in the override file’s
history explains why primary was mapped to background-success specifically for progress
bars; it is the same convention this checkout uses for the Loader’s bouncing-bar animation
color, which suggests a house habit of coloring “things that are working” green rather than a
decision made about ProgressBar on its own.
Status
No lifecycle metadata exists. There is no
status, since, deprecated, or
replacedBy field on a Titan component, so this table cannot report when an export arrived or
whether it is on the way out.Related
The generated adoption report for this component shows zero usages, matched against a literal<Progress /> JSX tag — which is not the real import name. Since the actual export and
call sites use LinearProgress, this figure is very likely a tag-matching artifact rather than
evidence the component is genuinely unused anywhere in the product. Treat it as unreliable
rather than as a recommendation either way.
- Skeleton · Spinner — the other two loading primitives, split by whether the shape or the duration is known
Loader— a separate, unrelated component in this same package (a five-bar bounce animation, not a track), heavily adopted across applications per its own generated usage data, and currently undocumented in this site. Not the same thing as this page and not interchangeable with it.