Progress
A horizontal progress bar that communicates task completion. It supports a determinate mode (a
known value out of a max) and an indeterminate mode (animated sweep) for tasks with no
measurable progress. State is expressed through ARIA attributes — aria-valuenow is omitted when
indeterminate, giving screen readers the correct cue automatically.
The examples are organised by layer: the class reference is the standalone
@oriui/css layer, and the Framework API is the @oriui/vue component. Every
example is live — flip its code between HTML (the standalone classes, also your htmx / Astro / Svelte /
plain-HTML usage), Vue; HTML is the default.
Classes
A progress bar is a block class plus single-class token utilities. The Vue props in Framework API map 1:1 to these.
| Class | Type | Description |
|---|---|---|
ori-progress | Block | Required base class. Renders full-width. Defaults baked in: color primary, radius rounded, height 8 px. |
ori-progress_sm · ori-progress_md · ori-progress_lg | Size | Track height: 4 px (sm) · 8 px (md, default) · 12 px (lg). ori-progress_* (size sugar). |
ori-color_* | Color | primary · secondary · success · warn · danger · info · surface — one class repoints the color token; no base class needed. |
ori-size-radius_* | Radius | zero · xs · sm · md · lg · xl · rounded (default) — one class repoints the radius token; no base class needed. |
ori-progress__track | Part | Inner track element (tinted background). |
ori-progress__indicator | Part | Fill element; width driven by inline style or data-indeterminate animation. |
data-indeterminate | State | Present on the indicator when no value is known; triggers the sweep animation. |
Determinate
Pass a value (0–max). The fill width and aria-valuenow update together.
<!-- width is set via inline style on the indicator -->
<div
class="ori-progress ori-color_primary"
role="progressbar"
aria-label="Loading"
aria-valuemin="0"
aria-valuemax="100"
aria-valuenow="50"
>
<div class="ori-progress__track">
<div class="ori-progress__indicator" style="width: 50%"></div>
</div>
</div>
Indeterminate
Omit value (or pass :indeterminate="true") when progress cannot be measured. The indicator
sweeps continuously and aria-valuenow is not set.
<div
class="ori-progress ori-color_primary"
role="progressbar"
aria-label="Loading"
aria-valuemin="0"
aria-valuemax="100"
>
<div class="ori-progress__track">
<div class="ori-progress__indicator" data-indeterminate></div>
</div>
</div>
Colors
Every semantic role. color defaults to primary; set it to any role to recolor the indicator.
<!-- swap the color class: ori-color_primary → _secondary / _success / _warn / _danger / _info -->
<div
class="ori-progress ori-color_danger"
role="progressbar"
aria-label="Loading"
aria-valuemin="0"
aria-valuemax="100"
aria-valuenow="60"
>
<div class="ori-progress__track">
<div class="ori-progress__indicator" style="width: 60%"></div>
</div>
</div>
Sizes
Three track heights — sm (4 px), md (8 px, default), and lg (12 px).
<!-- swap the size modifier: ori-progress_sm / ori-progress_md / ori-progress_lg -->
<div
class="ori-progress ori-progress_lg ori-color_primary"
role="progressbar"
aria-label="Loading"
aria-valuemin="0"
aria-valuemax="100"
aria-valuenow="50"
>
<div class="ori-progress__track">
<div class="ori-progress__indicator" style="width: 50%"></div>
</div>
</div>
Radius
From zero (square) to rounded (pill, default).
<!-- swap the radius class: ori-size-radius_zero → _sm / _md / _rounded -->
<div
class="ori-progress ori-progress_lg ori-size-radius_zero ori-color_primary"
role="progressbar"
aria-label="Loading"
aria-valuemin="0"
aria-valuemax="100"
aria-valuenow="60"
>
<div class="ori-progress__track">
<div class="ori-progress__indicator" style="width: 60%"></div>
</div>
</div>
Custom max
max defaults to 100. Pass any positive number and supply value in the same unit — the
component calculates the fill percentage.
<div
class="ori-progress ori-color_success"
role="progressbar"
aria-label="Step 3 of 10"
aria-valuemin="0"
aria-valuemax="10"
aria-valuenow="3"
>
<div class="ori-progress__track">
<div class="ori-progress__indicator" style="width: 30%"></div>
</div>
</div>
Common patterns
An upload bar with a label and a multi-step wizard indicator.
<div style="display: flex; flex-direction: column; gap: 0.25rem">
<span style="font-size: 0.875rem">Uploading… 68 %</span>
<div
class="ori-progress ori-progress_sm ori-color_primary"
role="progressbar"
aria-label="Uploading file"
aria-valuemin="0"
aria-valuemax="100"
aria-valuenow="68"
>
<div class="ori-progress__track">
<div class="ori-progress__indicator" style="width: 68%"></div>
</div>
</div>
</div>
<div
class="ori-progress ori-color_secondary"
role="progressbar"
aria-label="Step 2 of 5"
aria-valuemin="0"
aria-valuemax="5"
aria-valuenow="2"
>
<div class="ori-progress__track">
<div class="ori-progress__indicator" style="width: 40%"></div>
</div>
</div>
Accessibility
The accessibility contract holds across every layer — the standalone classes and the Vue component render the same attributes.
- Renders a
<div role="progressbar">witharia-valuemin="0",aria-valuemax, andaria-valuenowset fromvalueandmax. - In indeterminate mode
aria-valuenowis omitted — the WAI-ARIA spec says a progressbar withoutaria-valuenowis implicitly indeterminate, which assistive technology announces accordingly. - The
labelprop setsaria-label. Always supply a meaningful label so screen readers can distinguish multiple bars on the same page (e.g."Uploading avatar"vs"Saving settings"). - The fill animation respects
prefers-reduced-motion: the transition on the determinate indicator is removed and the indeterminate sweep freezes to a fully-filled bar. - The component is not interactive — no keyboard interaction is defined.
Framework API
The props, events, and slots of the Vue component. The standalone CSS layer has no component API — its surface is the classes above. (Svelte bindings are planned.)
Props
| Prop | Type | Default | Description |
|---|---|---|---|
color | ThemeColor | 'primary' | Semantic color role for the indicator. (The standalone .ori-progress class inherits currentcolor when no ori-color_* utility is applied.) |
indeterminate | boolean | false | Enables the animated sweep; omits aria-valuenow from the rendered element. |
label | string | 'Loading' | aria-label read by assistive technology. Use a descriptive message per-bar. |
max | number | 100 | Upper bound. value is clamped to this range before the percentage is computed. |
radius | RadiusSize | 'rounded' | Corner radius of the track and indicator (zero · xs · sm · md · lg · xl · rounded). |
size | 'sm' | 'md' | 'lg' | 'md' | Track height: sm = 4 px, md = 8 px, lg = 12 px. |
value | number | 0 | Current progress value, clamped to [0, max]. Ignored when indeterminate is true. |
ThemeColor: 'primary' | 'secondary' | 'success' | 'warn' | 'danger' | 'info' | 'surface' | 'background'
RadiusSize: 'zero' | 'xs' | 'sm' | 'md' | 'lg' | 'xl' | 'rounded'
Events & attributes
OriProgress declares no custom events and does not set inheritAttrs: false, so any extra
attributes you pass (class, style, data-*) fall through to the root <div role="progressbar">.
The ARIA attributes (aria-label, aria-valuemin, aria-valuemax, aria-valuenow) are bound
directly from props — set them through props rather than as fall-through attributes.
Slots
OriProgress has no slots. Its visual output is a CSS-driven track and fill bar controlled entirely by props.