Skip to main content

Theme config

Theme mode

Color palette

Grays

Border radii/radiuses/radiopedes/you know
Border radius
Field border radius
Button border radius
All
Components
Guides
API
Recent

Components

Progress

See also: Spinner.

Indeterminate

---
import { Progress } from "@opui/astro"
---
<Progress aria-busy="true" />
<div class="ui-progress"><progress aria-busy="true"></progress></div>

Determinate

---
import { Progress } from "@opui/astro"
---
<Progress id="determinate-progress" max="100" value="10" />
<script>
const progress = document.querySelector(
"#determinate-progress",
) as HTMLProgressElement
if (progress) {
setInterval(() => {
if (progress.value >= 100) {
progress.value = 10
} else {
progress.value += 10
}
}, 3000)
}
</script>
<script type="module">
const e = document.querySelector("#determinate-progress");
e &&
setInterval(() => {
e.value >= 100 ? (e.value = 10) : (e.value += 10);
}, 3e3);
</script>
<div class="ui-progress">
<progress id="determinate-progress" max="100" value="10"></progress>
</div>

Variants

Use the variant prop to swap the progress bar track surface for better contrast on different backgrounds.

---
import { Progress } from "@opui/astro"
---
<Progress value="25" max="100" variant="default" />
<Progress value="50" max="100" variant="filled" />
<Progress value="75" max="100" variant="tonal" />
<div class="ui-progress ui-default">
<progress max="100" value="25"></progress>
</div>
<div class="ui-progress ui-filled">
<progress max="100" value="50"></progress>
</div>
<div class="ui-progress ui-tonal">
<progress max="100" value="75"></progress>
</div>

Accessibility

If the <progress> element is describing the loading progress of a section of a page:

  • use aria-describedby to point to the status
  • set aria-busy="true" on the section that is being updated, removing it when loading is finished.

Source: MDN

Content here is loading.

API

Prop Type Default Description
value number | string - The current value of the progress bar.
max number | string - The maximum value of the progress bar.
aria-busy "true" | "false" | boolean - Indicates that the element or its content is being modified.
aria-label string - Accessible label for the progress bar.
variant 'filled' | 'default' | 'tonal' 'default' Adjusts the progress bar background color for better contrast on different surfaces.

Installation

@layer components.root {
:where(.ui-progress) {
--_accent-color: var(--primary);
--_bg-color: var(--surface-tonal);
background-color: var(--_bg-color);
block-size: var(--size-1);
border-radius: var(--border-radius, 0.25rem);
display: inline-block;
inline-size: 100%;
overflow: hidden;
position: relative;
vertical-align: baseline;
/* Color */
&.ui-filled {
--_bg-color: var(--surface-filled);
}
&.ui-default {
--_bg-color: var(--surface-default);
}
&.ui-tonal {
--_bg-color: var(--surface-tonal);
}
& > progress {
appearance: none;
background: none;
block-size: 100%;
border: 0;
display: block;
inline-size: 100%;
&::-webkit-progress-bar {
background: none;
border-radius: var(--border-radius, 0.25rem);
}
&[value]::-webkit-progress-value {
background-color: var(--_accent-color);
@media (prefers-reduced-motion: no-preference) {
transition: inline-size 0.2s
var(--ease-out-4, cubic-bezier(0, 0, 0.1, 1));
}
}
&::-moz-progress-bar {
background-color: var(--_accent-color);
}
}
}
@media (prefers-reduced-motion: no-preference) {
:where(.ui-progress):has(> progress:indeterminate) {
&::after {
animation: indeterminate 2s linear infinite;
background-color: var(--_accent-color);
content: "";
inset: 0 auto 0 0;
position: absolute;
will-change: inset-inline-start, inset-inline-end;
}
& > progress {
&::-webkit-progress-value {
background-color: transparent;
}
&::-moz-progress-bar {
background-color: transparent;
}
}
}
[dir="rtl"] {
:where(.ui-progress):has(> progress:indeterminate) {
&::after {
animation-direction: reverse;
}
}
}
}
@keyframes indeterminate {
0% {
inset-inline-start: -200%;
inset-inline-end: 100%;
}
60% {
inset-inline-start: 107%;
inset-inline-end: -8%;
}
100% {
inset-inline-start: 107%;
inset-inline-end: -8%;
}
}
}