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-describedbyto 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%; } }}