Acessibilidade
WCAG AA por padrão. Cada componente do sistema implementa um padrão ARIA documentado — não é decoração, é contrato.
Princípios
Quatro pilares
WCAG 2.2 organiza acessibilidade em perceptível, operável, compreensível e robusto. Sinapse persegue nível AA como mínimo.
Perceptível
Alternativa textual em ícones, contraste mínimo 4.5:1 em texto, focus visível, conteúdo não depende só de cor.
Operável
Tudo via teclado. Tab/Shift+Tab cobre rota completa. Sem trap de foco em overlays. Atalhos previsíveis.
Compreensível
Linguagem clara, ordem lógica, erros explicados, label associado a input via for/id ou aria-labelledby.
Robusto
HTML válido, ARIA semântico (button vs role=button), parsing confiável por leitores de tela.
Padrões ARIA
Implementados no sistema
Cada componente segue um padrão da APG (ARIA Authoring Practices Guide). Nada é improviso.
| Componente | Padrão APG | Comportamento garantido |
|---|---|---|
| Select | combobox 1.2 | Listbox custom, navegação ↑↓ Home/End, Enter seleciona, Esc fecha, type-ahead. |
| Modal | dialog (modal) | Trap de foco, Esc fecha, retorna foco ao trigger, aria-labelledby para o título. |
| Tabs | tablist + tabpanel | ← → entre tabs, Home/End extremos, aria-selected, painel via aria-labelledby. |
| Side Panel | dialog + tablist interno | Drawer com tabs internas. Esc fecha, retorna foco ao trigger. |
| Tooltip | tooltip + aria-describedby | Hover e focus revelam, conteúdo associado ao trigger via describedby. |
| Toast | live region (status) | role=status anuncia feedback transient sem interromper. role=alert para erros críticos. |
| Callout | role=status | Anúncio polite. Não rouba foco. Mudança de status comunicada. |
| Breadcrumb | nav + ol + aria-current | Landmark navegacional, item atual marcado, separadores aria-hidden. |
| Pagination | nav + button labels | aria-label descritivo em cada botão, como Página 3 ou Próxima página. |
| Field | label + aria-describedby | Label associado via for/id, support text e error via describedby, aria-invalid em erro. |
Foco
Visível, sempre
focus-visible
focus-visible:outline-none
focus-visible:ring-2
focus-visible:ring-primary
focus-visible:ring-offset-2 Por que focus-visible
:focus mostra ring após click do mouse.
:focus-visible mostra foco quando a navegação precisa dele,
mantendo legibilidade visual sem sacrificar acessibilidade.
Contraste
WCAG mínimos
| Elemento | AA | AAA | Token Sinapse |
|---|---|---|---|
| Texto normal (<18px) | 4.5:1 | 7:1 | text-foreground · text-muted-foreground |
| Texto grande (≥18px ou 14px bold) | 3:1 | 4.5:1 | text-muted-foreground (mínimo permitido) |
| UI (borda, ícone) | 3:1 | — | border-border · text-foreground |
| Focus ring | 3:1 vs adjacente | — | ring-primary |
Teclado
Atalhos universais
Próximo elemento focável
Elemento focável anterior
Ativar button, link ou listbox option
Toggle em checkbox/switch ou ativar button
Fechar overlay: modal, panel, tooltip ou dropdown
Navegação dentro de listbox ou radio group
Navegação entre tabs
Primeiro ou último item em coleções
Anti-patterns
O que nunca fazer
| Evite | Por quê | Corrija com |
|---|---|---|
<div onclick="..."> | Div não recebe foco e não responde a teclado. | <button> ou role=button + tabindex=0 + onkeydown |
placeholder como label | Some ao digitar, baixo contraste, leitor de tela inconsistente. | <label> visível associado via for/id |
outline: none | Remove foco visível e quebra navegação por teclado. | focus-visible:ring-2 ring-primary |
aria-label em texto visível | Sobrescreve o texto para leitores de tela e confunde. | Deixar texto visível ser o accessible name |
cor como único sinal | Falha em daltonismo, modo monocromático e baixa visão. | Cor + ícone + texto de estado explícito |
Ferramentas
Validação contínua
axe DevTools
Auditoria automatizada no browser. Detecta parte relevante das issues estruturais.
Lighthouse
Score de acessibilidade integrado ao Chrome DevTools.
NVDA / VoiceOver
Teste real com leitor de tela. Insubstituível.
Teclado apenas
Completar tarefa sem mouse. Detecta trap, ordem ilógica e foco invisível.