Spinner
ui-spinner is a small rotating arc that shows work in progress. It has the role status and an accessible
name taken from label, which defaults to "Loading". By default it inherits the current text colour. variant
picks a theme colour instead.
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Spinner 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/spinner.html"></import-element>
<ui-spinner></ui-spinner>
</body>
</html>Examples
Sizes
size is the width and height in pixels, at least 8.
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Spinner 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/spinner.html"></import-element>
<ui-spinner size="12"></ui-spinner>
<ui-spinner size="16"></ui-spinner>
<ui-spinner size="24"></ui-spinner>
<ui-spinner size="32"></ui-spinner>
</body>
</html>Colour
variant sets the colour of the arc. The default variant uses currentColor, so it matches the surrounding
text.
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Spinner 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/spinner.html"></import-element>
<ui-spinner size="24"></ui-spinner>
<ui-spinner size="24" variant="primary"></ui-spinner>
<ui-spinner size="24" variant="muted"></ui-spinner>
<ui-spinner size="24" variant="destructive"></ui-spinner>
</body>
</html>In a button
Show a spinner inside a disabled button while a request runs.
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Spinner 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/spinner.html"></import-element>
<import-element from="./spinner-button-demo.html"></import-element>
<spinner-button-demo></spinner-button-demo>
</body>
</html><custom-element name="spinner-button-demo">
<script>
const request = useState({ busy: false });
function save() {
request.busy = true;
const timer = setTimeout(() => {
request.busy = false;
}, 1500);
signal.addEventListener("abort", () => clearTimeout(timer), { once: true });
}
</script>
<ui-button _disabled="#request.busy" onclick="save()">
<is-visible when="#request.busy"><ui-spinner size="14" label="Saving"></ui-spinner></is-visible>
Save changes
</ui-button>
</custom-element>With a badge
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Spinner 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/badge.html"></import-element>
<import-element from="https://cdn.jsdelivr.net/npm/@realmorg/ui@alpha/components/spinner.html"></import-element>
<ui-badge variant="secondary"><ui-spinner size="12" label="Syncing"></ui-spinner> Syncing</ui-badge>
<ui-badge variant="outline"><ui-spinner size="12" label="Processing"></ui-spinner> Processing</ui-badge>
</body>
</html>Custom label
Change label to describe the work. It becomes the spinner's accessible name.
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Spinner 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-row-tight {
display: flex;
flex-wrap: wrap;
align-items: center;
gap: calc(var(--spacing) * 2);
}
.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/spinner.html"></import-element>
<div class="demo-row-tight demo-muted">
<ui-spinner label="Loading messages"></ui-spinner>
Loading messages…
</div>
</body>
</html>API
Parts
| Part | Slot | Renders |
|---|---|---|
ui-spinner |
(default) | A rotating arc drawn with an inline <svg>. It has no slot and takes no content. |
Attributes
| Attribute | Type | Default | Description |
|---|---|---|---|
size |
number | 16 |
Width and height in pixels. Minimum 8. |
label |
string | "Loading" |
Accessible name of the spinner. |
variant |
"default" | "primary" | "muted" | "destructive" |
"default" |
Colour of the arc. default uses currentColor. |
CSS parts
None. Set color on the element to use a colour outside the variants.
Accessibility
The element has the role status and its aria-label comes from label, both through ElementInternals. The
SVG is hidden from assistive technology. With reduced motion preferred, the rotation slows to a third of its
normal speed instead of stopping, so the indicator still shows that something is happening.