Component · Astro + CSS · no JavaScript
Logo loader
The header pinwheel spins while something loads. When it is done, the spin eases out, the mark folds into a Signal disc and the tick draws itself in. One file, drops into src/components/ui/ in maximus-web.
In a button
18px, tone="on-signal" on the primary button, default tone on the secondary.
Submitting…SubmittedSending…Sent
Install
Download LogoLoader.astro and save it as:
src/components/ui/LogoLoader.astroIt uses the V5.1.4 tokens already in maximus-web (--color-signal, with a fallback), needs no package and ships no script.
Use
---
import LogoLoader from '../components/ui/LogoLoader.astro';
---
<LogoLoader /> <!-- 24px, spinning -->
<LogoLoader size={48} />
<LogoLoader size={48} state="done" label="Saved" />Switch to done
The loader never decides when loading ends. Whatever already ends it (the server render, the form handler the site already has) sets one attribute, and the CSS does the rest.
<!-- 1. On the loader itself -->
<LogoLoader size={32} state="done" /> <!-- renders data-state="done" -->
<!-- 2. On any ancestor: every loader inside switches -->
<form data-loader-state="done"> … </form>
<!-- 3. CSS only: a checked .ml-loader-toggle that is a direct child of an ancestor -->
<div>
<input type="checkbox" class="ml-loader-toggle" id="done" />
<LogoLoader />
</div>Button markup
<button class="btn-primary" type="submit">
<LogoLoader size={18} tone="on-signal" label="Submitting" />
Submitting…
</button>Props
| Prop | Type | Default | Notes |
|---|---|---|---|
size | number | 24 | Width and height in px. 16, 24, 32, 48 and 72 are the tested sizes. The tick stroke gets heavier at 32 and below. |
state | 'loading' | 'done' | 'loading' | Initial state, written to data-state. Done plays the settle, fold and tick once. |
tone | 'default' | 'on-signal' | 'default' | on-signal is for Signal-blue surfaces: white mark, white disc, blue tick. |
label | string | 'Loading' | Accessible name. The loader has role="status". |
class | string | | Extra classes on the root span. |
Motion
- Spin: one turn every 0.95s, linear.
- Done: the spin pauses where it is while an outer layer turns a further 90° on ease-out-cubic over 0.7s, so it slows from the same speed instead of jumping.
- The mark shrinks and fades (0.3s), the Signal disc pops in with a small overshoot (0.52s), a Sky ring pings out, and the tick draws (0.38s). About 1.2s in total.
prefers-reduced-motion: no spin. The mark breathes while loading, then crossfades to the finished tick.