Toggle
Buton-icon care ține o stare. În repaus e un cerc cu contur, gol; selectat, forma se strânge și se umple cu brand. Scara e a butonului-icon (26/30/40/44). Propunere — de validat pe un ecran real.
Markup canonic · components/toggle.json
Stări
| Stare | Formă | Fundal | Icon | Contrast |
|---|---|---|---|---|
| repaus | --r-full | transparent + contur --c-input-border-tonal | --c-fog | contur 3.13:1 · icon 4.37:1 |
| hover | --r-full | --c-bej-1 | --c-ink | 16.23:1 |
| press | --r-full | --c-bej-1 + contur --c-input-border-hover | --c-ink | 16.23:1 |
| selectat | --r-sm / --r-md | --c-accent | #fff | 3.67:1 — prag non-text 3:1 |
| selectat · hover | --r-sm / --r-md | --c-accent-deep | #fff | 5.39:1 |
| dezactivat | — | opacity: 0.4 | — | — |
Conturul din repaus e ce lipsea până în v8: fără el nu există vas, iar „oprit" citește ca „nu e nimic aici". Pragul non-text pentru conturul unui control e 3:1 (WCAG 1.4.11), măsurat pe fundalul real de pagină — --c-rule (0.10) dă 1.24:1 și --c-input-border (0.30) dă 2.00:1, amândouă pică. --c-input-border-tonal (0.46) dă 3.13:1.
Selectatul e --c-accent plin cu icon alb, nu --c-accent-tint cu icon deep. Alb pe accent dă 3.67:1 și trece, fiindcă un icon e non-text. Tooltipul stă la aceeași valoare ca abatere declarată, fiindcă el poartă text de 13px — nu e precedent pentru normă.
Metrici
scara .toggle.xs 26 · .toggle 30 · .toggle.md 40 · .toggle.lg 44 icon 14px pe 26 și 30 · 18px pe 40 și 44 (ca .btn.icon-only) repaus jumătatea cutiei, ca lungime · contur inset 1px --c-input-border-tonal selectat --r-sm pe 26 și 30 · --r-md pe 40 și 44 tranziția 180ms cubic-bezier(.4,0,.2,1) pe TOT: fundal, icon, rază, contur, filter .toggle-group carcasă pilulă cu contur · padding 3px · gap 2px · fundal transparent activ în grup pilulă --c-accent, icon alb — FĂRĂ morph de formă raza selectatului urcă o treaptă la 40 fiindcă morph-ul se citește ca raport între rază și jumătatea cutiei: o rază unică ar aluneca 0.77 → 0.45, iar așa stă în 0.77 / 0.67 / 0.70 / 0.64 — aceeași senzație pe toată scara. raza de repaus e jumătatea cutiei scrisă ca lungime, NU --r-full: browserul taie border-radius la jumătatea cutiei, deci de la 9999px animația e invizibilă până în ultima jumătate de procent din durată și forma sare la final.
Solo sau grup
aria-pressed. Grup = alegere exclusivă dintr-un set mic (aliniere, densitate, interval) — role="radiogroup" + role="radio" + aria-checked, cu roving tabindex și săgeți. Dacă opțiunile se exclud și sunt peste ~4, e .select, nu un toggle group.Regula formei: forma se schimbă doar acolo unde nu există un container care să declare setul. Solo n-are șină, deci forma ține locul ei — cercul se strânge și se umple. În grup, carcasa declară deja setul, deci itemul rămâne buton rotund în repaus și doar culoarea se schimbă. Consecința care contează: plin de brand = selectat are un singur înțeles, în ambele contexte.
În context — factură în editare
Regula practică de densitate: cele două grupuri de aici sunt pragul. Toggle-ul solo își poartă conturul, deci se citește ca acțiune disponibilă; roz-ul rămâne rezervat stărilor pornite. Dacă o bară ajunge să aibă mai mult roz decât titlul documentului, accentul a încetat să mai fie accent.