<!-- Generated by tools/docs.php from docs/src/progress.html - edit the source, not this file. -->

# Progress and meters

The browser's own `<progress>` for work under way and `<meter>` for a measure within known limits - a quota, a score. The value is an attribute, the browser announces it, and a progress without a value says the work has no known end.

## Examples

`progress` on a `<progress>` with `value` and `max`; the words of the value go beside the bar, `text-nowrap` so the bar gives way, and the label names it.

```html
<div class="form-field">
	<label class="form-label" for="progress-basic-upload">Uploading photos</label>
	<div class="hstack gap-12">
		<progress class="progress" id="progress-basic-upload" value="40" max="100">40 %</progress>
		<span class="text-muted fs-12 text-nowrap">40 %</span>
	</div>
</div>
<progress class="progress" aria-label="Rebuilding pages"></progress>
```

### Tones and sizes

`progress-{tone}` for the tones, `progress-sm` and `progress-lg` for the height; `progress-striped` lays stripes on the bar, `progress-animated` moves them while motion is allowed.

```html
<progress class="progress progress-success" value="75" max="100" aria-label="Published, 75 percent"></progress>
<progress class="progress progress-warning progress-sm" value="50" max="100" aria-label="Translated, 50 percent"></progress>
<progress class="progress progress-danger progress-lg" value="20" max="100" aria-label="Failed, 20 percent"></progress>
<progress class="progress progress-lg progress-striped progress-animated" value="60" max="100" aria-label="Deploying, 60 percent"></progress>
```

### Meters

`meter` on a `<meter>`: `low`, `high` and `optimum` divide the range, and the browser colours the value by the part it falls in - green in the good part, amber next to it, red in the far one.

```html
<div class="form-field">
	<label class="form-label" for="progress-meter-storage">Storage used</label>
	<div class="hstack gap-12">
		<meter class="meter" id="progress-meter-storage" value="3.1" min="0" max="10" low="7" high="9" optimum="0">3.1 of 10 GB</meter>
		<span class="text-muted fs-12 text-nowrap">3.1 of 10 GB</span>
	</div>
</div>
<meter class="meter" value="8" min="0" max="10" low="7" high="9" optimum="0" aria-label="Photos, 8 of 10 GB">8 of 10 GB</meter>
<meter class="meter" value="9.6" min="0" max="10" low="7" high="9" optimum="0" aria-label="Backups, 9.6 of 10 GB">9.6 of 10 GB</meter>
```

### Hairlines

`progress-xs`, 3 px, and `meter-xs`, 2 px, sit under a row's words without fighting them: how far a job is between its runs, amber when it is late, and how often it succeeded, colored by the meter's own parts.

```html
<div class="vstack gap-4">
	<span>Nightly backup <span class="text-muted fs-12">next in 2 h</span></span>
	<progress class="progress progress-xs" value="70" max="100" aria-label="Nightly backup, 70 percent of its cycle"></progress>
	<meter class="meter meter-xs" value="0.98" min="0" max="1" low="0.8" high="0.95" optimum="1" aria-label="Nightly backup, 98 percent succeeded">98%</meter>
</div>
<div class="vstack gap-4">
	<span>Mail queue <span class="text-muted fs-12">late by 6 min</span></span>
	<progress class="progress progress-xs progress-warning" value="100" max="100" aria-label="Mail queue, late"></progress>
	<meter class="meter meter-xs" value="0.71" min="0" max="1" low="0.8" high="0.95" optimum="1" aria-label="Mail queue, 71 percent succeeded">71%</meter>
</div>
```

### Along the window's top

`REDZ.ui.progress(promise)` shows a thin bar along the top of the window while a request runs, and answers the promise: it comes after 150 ms, so a quick answer shows nothing, then stays at least 400 ms, so it never flickers; however many requests run at once, there is one bar. It is `progress-top`, in the top layer, and readers do not hear it - what waits says so itself, a [busy](busy.md) region or button. Under reduced motion the bar stands still.

```html
<button class="btn" type="button" data-docs-run="progress"><i class="bi bi-cloud-arrow-down" aria-hidden="true"></i>Load for 2 seconds</button>
```

```js
const rows = await REDZ.ui.progress(fetch('/bookings?page=2').then((answer) => answer.json()));
```

A product sets how much it shows in its tokens: `--redz-progress-top-size`, `--redz-progress-top-track` and `--redz-progress-top-glow`, a `box-shadow`.

## Keyboard and accessibility

- Name every bar: a `<label for>`, `aria-label` or `aria-labelledby`. The browser announces the value as a percentage of `max`; the words beside the bar are for the eye.
- Colour is not the message: a meter in the red part also says so in words where it matters.
- A screen reader does not follow a bar as it fills: say the end of a long task in a notice, by `REDZ.ui.toast`.
- In forced colours the bar takes the system's highlight; right to left it fills from the right.

## Tokens

From [`css/components/progress.css`](https://github.com/redz-tech/REDZ.UI/blob/main/css/components/progress.css). It declares `--redz-track` on its root, never on rows or items.

It reads the theme's `--redz-bg-hover`, `--redz-primary`, `--redz-secondary`, `--redz-success`, `--redz-danger`, `--redz-warning`, `--redz-info`, `--redz-progress-top-track`, `--redz-progress-top-size`, `--redz-progress-top-glow`, `--redz-motion`, `--redz-ease`.

## From Bootstrap 5.3

| Bootstrap 5.3 | REDZ.UI | Change | Note |
| --- | --- | --- | --- |
| `progress` | `progress` | review | on a <progress value="40" max="100"> itself, not around a progress-bar with a width; a tone is progress-success and the like, not bg-* on the bar |
| `progress-bar` | - | remove | the browser draws the bar from value |
| `progress-bar-animated` | `progress-animated` | rename | it moves only while motion is allowed |
| `progress-bar-striped` | `progress-striped` | rename |  |
| `progress-stacked` | - | review | not planned: one <progress> a value |
