Spinner
Indicator de așteptare. Peste 24px e loader-ul Bono — la mărimea aia logo-ul se citește și momentul merită brandul. Sub 24px e un inel în brand: un logo la 16px e o pată, nu un logo.
Markup canonic · components/spinner.json
Scara
| Mărime | Clasă | Ce se randează | Unde |
|---|---|---|---|
| 32px | .spinner-brand.size-8 | loader Bono (Lottie) | încărcare de pagină sau de flow |
| 24px | .spinner-brand.size-6 | loader Bono (Lottie) | încărcare de secțiune, listă, card |
| 20px | .spinner.sm | inel CSS, brand | inline, lângă un text |
| 16px | .spinner.xs | inel CSS, brand | în buton, în rând de tabel |
Pragul e la 24px fiindcă sub el conturul logo-ului se închide vizual și animația nu se mai citește ca desen — devine o formă care pulsează.
Loader-ul Bono · assets/loader-bono.json
.spinner-brand.size-8 · 32px
.spinner-brand.size-6 · 24px
Lottie, 491×491, 120 de cadre la 60fps (2s, buclă). Două trasee desenate secvențial cu trim path: unul se desenează, celălalt îl urmează, apoi se șterg în aceeași ordine. Stroke #EE4379 — chiar --c-pink.
Compoziția e strânsă pe desen, nu pe artboard-ul din care a ieșit: 491×491, cât ține marca cu tot cu stroke. Așa .spinner-brand dimensionează marca, nu aerul din jurul ei — 32px de gazdă = 32px de logo, iar linia iese la 2.7px la size-8 și 2px la size-6, adică cel puțin cât inelul CSS de lângă. Primul export avea comp 800×800 cu desenul pe ~61% din el, și din asta inelul de 20px se desena mai mare decât loader-ul de 32px.
assets/loader-bono.json sursa animației compoziție 491 x 491 — strânsă pe desen .spinner-brand gazda — 32px (size-8) sau 24px (size-6) stroke 41 în comp = 2.7px la 32px, 2px la 24px loop infinit, 2s culoare #EE4379 (--c-pink), coaptă în JSON
Clasa e doar o cutie goală de 24 sau 32px: animația vine din JSON și are nevoie de un player la runtime. În aplicație e lottie-web, montat peste .spinner-brand. Pagina asta nu aduce o dependență pentru o singură componentă — o randează cu components/_lottie.js, care citește chiar assetul (traseele, culoarea și cadrele se iau din JSON, nu sunt copiate în cod).
Culoarea e coaptă în JSON: se potrivește cu --c-pink, dar nu îl urmărește — e o copie, nu o referință. Dacă tokenul se schimbă, animația trebuie re-exportată. E singurul artefact din sistem cu valoarea închisă în el, și de asta e notat aici.
Accesibilitate
role="status" aria-label="Se încarcă" pe spinner
aria-busy="true" pe regiunea care se încarcă
prefers-reduced-motion inelul încetinește la 2s, bucla loader-ului
trece la 4s — nu se opresc
Un spinner fără role și fără etichetă e invizibil pentru cititorul de ecran: pagina pare doar goală.