Ir ao conteúdo
SEED engenhariaDesign System

Componentes

8. Switch

estávelseed-componentes.md v1.43 · §08seção 10 de 9808-switch-estavel-validado-pelo-rafael-em-2026-08.md · MD5 91466a2f

Título completo no canon: Switch — estável · validado pelo Rafael em 2026-08-03 (preview v0.13 + suite de 63 testes)

Base (3 rodadas, 2026-08-02): R1 — NN/g toggles (efeito imediato, nunca com submit), UX Movement (sinal só no ON; system state × contextual state), UXTweak. R2 — M3 ("the preferred way to adjust settings on mobile"), iOS HIG, padrões de pending async. R3 — APG switch role, Roselli (mixed inválido), TalkBack/checkbox+role. Decisões K1–K6 conferidas pelo Rafael no consolidado de 2026-08-02.

8.1 Papel, fronteiras e a exceção declarada#

Binário de AÇÃO com efeito IMEDIATO: liga e a coisa acontece (notificação ativada, módulo habilitado). Exceção formal ao G4 (§7.2): o G4 proíbe mudança de contexto ao selecionar VALOR; o switch é AÇÃO por contrato — o efeito imediato é a identidade (NN/g), e por isso ele NUNCA aparece em formulário com botão salvar (lá o binário é checkbox — régua §7.1 emendada). Filtros de busca/lista são estado contextual → checkbox, não switch.

8.2 Decisões K1–K6#

# Decisão Porquê Descartado
K1 Efeito imediato sempre; proibido em form com submit NN/g: misturar = usuário não sabe se salvou Switch "que espera o salvar" (é um checkbox fantasiado)
K2 Async: estado pending com spinner NO próprio switch; falha → REVERTE + toast com erro Silêncio ou delay sem sinal = loop de reenvio Confirmar otimista sem reverter (mente o estado)
K3 Sinal de cor só no ON (--seed-switch-on-bg = action-primary); OFF neutro (cinza), nunca vermelho; nunca "ON/OFF" escrito no trilho UX Movement: off colorido vira comando ambíguo; herda os 3 sinais do §1.5.1: cor + posição do thumb + movimento Verde/vermelho (semáforo em setting é alarme falso)
K4 Rótulo: o que o ON faz, verbo no infinitivo ou substantivo, ≤3 palavras ("Notificações por e-mail", "Modo escuro"), e NUNCA muda com o estado APG: rótulo que muda quebra a referência do leitor de tela "Ativado"/"Desativado" como rótulo dinâmico
K5 Implementação: <input type="checkbox" role="switch"> nativo; Space alterna; mixed é INVÁLIDO no role (vira false) Roselli/APG; checked nativo funciona em todo AT; TalkBack anuncia certo Div+ARIA do zero (reinventa foco/teclado)
K6 Mobile/app: switch é o controle padrão de settings (M3/iOS); grupos de switch usam fieldset+legend (§2.6b) Convenção de plataforma Checkbox em lista de settings de app (estranho ao OS)

8.3 Anatomia, tokens e estados#

Trilho 44×24 + thumb 20 (hit area 44×44). Tokens de componente — todos medidos em 2026-08-26, e a medição mudou dois valores da redação anterior: --seed-switch-off-bg (light cinza-500 #788F9D = 3,38:1 · dark cinza-600 #617683 = 3,92:1), --seed-switch-on-bg (= --seed-action-primary: turquesa-600 #098475 4,60:1 light / turquesa-300 #66D1C2 10,16:1 dark), --seed-switch-thumb = o thumb DESLIGADO (branco / cinza-100) e --seed-switch-thumb-on = o thumb LIGADO (= --seed-text-on-action-primary: branco / #00352F), foco = anel padrão.

O QUE A MEDIÇÃO ACHOU, e por que a redação anterior não podia achar. A linha antiga mandava "3:1 sobre a página: medir na produção do preview". A medição foi feita e deu 1,91 para o cinza-300 — reprovando a própria cláusula. Mas o defeito maior é que medir contra a página é medir metade do componente: o thumb é BRANCO, e branco sobre cinza-300 dá os mesmos 1,91 — o thumb sumia dentro do trilho, e a posição do thumb é o único canal que separa ON de OFF (K3: nunca "ON/OFF" escrito no trilho). Cinza-500 conserta os dois pares de uma vez (3,38 contra a página e 3,38 contra o thumb) e é o primeiro degrau da escala que atende — o cinza-400 ainda reprova, com 2,53. Nenhuma cor nova entrou (§14.1). ⭐⭐ E no tema ESCURO quem reprovava era o estado LIGADO, não o desligado — thumb cinza-100 sobre o trilho ligado dá 2,25. Ninguém tinha visto porque a cláusula só mandava medir o OFF. A saída também não precisou de cor nova: "o que vai sobre a superfície de ação" já é um par medido e canonizado, o --seed-text-on-action-primary, e o thumb de um switch ligado é exatamente isso — 7,39:1. No tema claro os dois thumbs coincidem em branco, então a regra é uma só, expressa em dois tokens que colapsam no claro. ⚠ Dois erros de NOME nesta mesma linha, consertados junto: ela apontava para --seed-action-primary-bg, que é o token fantasma da FF-P2/FF-P3 — removido do acervo —, e dizia "turquesa-400 sobre dark" quando action-primary no escuro é #66D1C2 = turquesa-300. ⭐ Spec que aponta para nome morto passa em toda guarda de valor, porque não há valor nenhum para conferir. Estados: off · on · off-hover · on-hover · focus · pending (spinner 14px no thumb, aria-busy) · disabled · readonly (§2: exibe sem permitir — borda, não opacidade). Movimento do thumb: 120ms --seed-ease-out; prefers-reduced-motion: sem animação, posição muda seca.

8.4 Microcopy e live region#

Rótulo à esquerda, switch à direita (padrão settings). Ajuda opcional abaixo do rótulo explica a CONSEQUÊNCIA ("Você receberá o resumo semanal"). Async: live region §1.13 anuncia "Notificações ativadas" / falha role="alert": "Não foi possível ativar. Tente novamente." — e o switch VOLTA.

8.5 Código — essência#

<label class="seed-switch-row">
  <span class="seed-switch-label">Notificações por e-mail</span>
  <input type="checkbox" role="switch" class="seed-switch">
</label>
.seed-switch{appearance:none;width:44px;height:24px;border-radius:999px;background:var(--seed-switch-off-bg);position:relative;cursor:pointer;transition:background .12s}
.seed-switch::after{content:"";position:absolute;top:2px;left:2px;width:20px;height:20px;border-radius:999px;background:var(--seed-switch-thumb);transition:left .12s var(--seed-ease-out)}
.seed-switch:checked{background:var(--seed-switch-on-bg)}
.seed-switch:checked::after{left:22px}
.seed-switch:focus-visible{outline:none;box-shadow:var(--seed-focus-ring)}
@media (prefers-reduced-motion:reduce){.seed-switch,.seed-switch::after{transition:none}}

8.6 Os 7 testes#

  1. Trilho off 3:1 sobre página (medir no preview). 2. Estado por cor + POSIÇÃO do thumb + movimento (3 sinais §1.5.1 — o teste WebEx que originou a regra). 3. Grayscale: posição do thumb carrega sozinha. 4. Par off × on distinguível a 1s (posição). 5. Um switch = uma ação. 6. Estado visível sem interação. 7. 44px de alvo; row inteira clicável. ✅
BancadaSEED DS v2 — Bloco 2 · Preview v0.13 (13/13)abrir em página própria ↗

Também cita o §8: tela-configuracoes.

Esc