Progress
ui-progress renders a native <progress> element styled as a thin rounded bar. Set value, and optionally
max, to show how much of a task is done. The bar is as wide as its container, so size it with a wrapper.
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Progress demo</title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@realmorg/realm@alpha/dist/realm.css">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@realmorg/ui@alpha/dist/theme.css">
<script type="module" src="https://cdn.jsdelivr.net/npm/@realmorg/realm@alpha/dist/realm.js"></script>
<style>
.demo-narrow {
width: min(100%, calc(var(--spacing) * 88));
}
</style>
</head>
<body>
<import-element from="https://cdn.jsdelivr.net/npm/@realmorg/ui@alpha/components/progress.html"></import-element>
<div class="demo-narrow">
<ui-progress value="60" aria-label="Progress"></ui-progress>
</div>
</body>
</html>Examples
Custom maximum
max defaults to 100. Set it to the total so value can be a plain count.
3 of 8 steps
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Progress demo</title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@realmorg/realm@alpha/dist/realm.css">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@realmorg/ui@alpha/dist/theme.css">
<script type="module" src="https://cdn.jsdelivr.net/npm/@realmorg/realm@alpha/dist/realm.js"></script>
<style>
.demo-narrow {
width: min(100%, calc(var(--spacing) * 88));
}
.demo-stack-tight {
display: grid;
gap: calc(var(--spacing) * 2);
}
.demo-text {
margin: 0;
font-size: var(--text-sm);
}
</style>
</head>
<body>
<import-element from="https://cdn.jsdelivr.net/npm/@realmorg/ui@alpha/components/progress.html"></import-element>
<div class="demo-narrow demo-stack-tight">
<p class="demo-text">3 of 8 steps</p>
<ui-progress value="3" max="8" aria-label="Steps completed"></ui-progress>
</div>
</body>
</html>With a label
Show the task name and percentage as text next to the bar.
Uploading report.pdf
45%
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Progress demo</title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@realmorg/realm@alpha/dist/realm.css">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@realmorg/ui@alpha/dist/theme.css">
<script type="module" src="https://cdn.jsdelivr.net/npm/@realmorg/realm@alpha/dist/realm.js"></script>
<style>
.demo-narrow {
width: min(100%, calc(var(--spacing) * 88));
}
.demo-stack-tight {
display: grid;
gap: calc(var(--spacing) * 2);
}
.demo-row-tight {
display: flex;
flex-wrap: wrap;
align-items: center;
gap: calc(var(--spacing) * 2);
}
.demo-text {
margin: 0;
font-size: var(--text-sm);
}
.demo-muted {
margin: 0;
font-size: var(--text-sm);
color: var(--muted-foreground);
}
</style>
</head>
<body>
<import-element from="https://cdn.jsdelivr.net/npm/@realmorg/ui@alpha/components/progress.html"></import-element>
<div class="demo-narrow demo-stack-tight">
<div class="demo-row-tight">
<p class="demo-text">Uploading report.pdf</p>
<p class="demo-muted">45%</p>
</div>
<ui-progress value="45" aria-label="Uploading report.pdf"></ui-progress>
</div>
</body>
</html>Driven by state
Bind value with _value. The bar animates between values.
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Progress demo</title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@realmorg/realm@alpha/dist/realm.css">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@realmorg/ui@alpha/dist/theme.css">
<script type="module" src="https://cdn.jsdelivr.net/npm/@realmorg/realm@alpha/dist/realm.js"></script>
</head>
<body>
<import-element from="https://cdn.jsdelivr.net/npm/@realmorg/ui@alpha/components/button.html"></import-element>
<import-element from="https://cdn.jsdelivr.net/npm/@realmorg/ui@alpha/components/progress.html"></import-element>
<import-element from="./progress-upload-demo.html"></import-element>
<progress-upload-demo></progress-upload-demo>
</body>
</html><custom-element name="progress-upload-demo">
<script>
const upload = useState({ percent: 13 });
function advance() {
upload.percent = upload.percent >= 100 ? 0 : Math.min(100, upload.percent + 22);
}
</script>
<style>
:host {
display: flex;
align-items: center;
gap: calc(var(--spacing) * 4);
width: 70%;
}
ui-progress {
flex: 1;
}
span {
min-width: calc(var(--spacing) * 10);
font-size: var(--text-sm);
font-variant-numeric: tabular-nums;
}
</style>
<ui-progress _value="#upload.percent"></ui-progress>
<span><slot name="#upload.percent"></slot>%</span>
<ui-button size="sm" variant="outline" onclick="advance()">Advance</ui-button>
</custom-element>Custom colour
The bar uses var(--primary). Set --primary on a wrapping element to recolour the bar and its track.
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Progress demo</title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@realmorg/realm@alpha/dist/realm.css">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@realmorg/ui@alpha/dist/theme.css">
<script type="module" src="https://cdn.jsdelivr.net/npm/@realmorg/realm@alpha/dist/realm.js"></script>
<style>
.demo-narrow {
width: min(100%, calc(var(--spacing) * 88));
}
.demo-stack {
display: grid;
gap: calc(var(--spacing) * 4);
}
</style>
</head>
<body>
<import-element from="https://cdn.jsdelivr.net/npm/@realmorg/ui@alpha/components/progress.html"></import-element>
<div class="demo-narrow demo-stack">
<div style="--primary: var(--chart-2)">
<ui-progress value="80" aria-label="Storage used"></ui-progress>
</div>
<div style="--primary: var(--destructive)">
<ui-progress value="30" aria-label="Battery"></ui-progress>
</div>
</div>
</body>
</html>API
Attributes
| Attribute | Type | Default | Description |
|---|---|---|---|
value |
number | none | Current value, minimum 0. When it is left out the bar is indeterminate. |
max |
number | 100 |
Value that means complete, minimum 1. |
aria-label |
string | Accessible name, passed to the inner <progress>. Property name: label. |
Parts
ui-progress has no child parts. Its default slot takes fallback text inside the native <progress>, for example
45%, which browsers that support <progress> do not render.
CSS parts
| Part | Description |
|---|---|
bar |
The native <progress> element. Its height is calc(var(--spacing) * 2). |
Accessibility
The inner <progress> has the native progressbar role, with its value and maximum exposed to assistive
technology. Name it with aria-label on ui-progress, which is passed to the inner bar. A <label for> outside
cannot reach into the shadow root. Without value the bar is indeterminate and exposes no value.