ITpS

Fundamentos

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.

visibility

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.

keyboard

Operável

Tudo via teclado. Tab/Shift+Tab cobre rota completa. Sem trap de foco em overlays. Atalhos previsíveis.

translate

Compreensível

Linguagem clara, ordem lógica, erros explicados, label associado a input via for/id ou aria-labelledby.

verified

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 pro título.
Tabs tablist + tabpanel ↔ entre tabs, Home/End extremos, aria-selected, painel via aria-labelledby.
Side Panel 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 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 (Página 3, 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

Foco invisível é foco quebrado. Sinapse usa focus-visible para distinguir teclado de mouse — nada some.

Padrão de focus ring

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 — ruidoso. :focus-visible só mostra quando navegação por teclado, mantendo legibilidade visual sem sacrificar a11y.

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 (border, ícone) 3:1 border-border · icon-default
Focus ring 3:1 vs adjacente ring-primary

Teclado

Atalhos universais

Tab

Próximo elemento focável

Shift + Tab

Anterior

Enter

Ativar (button, link, listbox option)

Space

Toggle (checkbox, switch) ou ativar (button)

Esc

Fechar overlay (modal, panel, tooltip, dropdown)

↑ ↓

Navegação dentro de listbox, radio group

← →

Navegação entre tabs

Home / End

Primeiro / último em coleções

Anti-patterns

O que nunca fazer

<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 — quebra navegação por teclado.

→ focus-visible:ring-2 ring-primary
aria-label em texto visível

Sobrescreve o texto pra leitores de tela. Confunde.

→ Deixar texto natural ser o accessible name
cor como único sinal

Daltonismo, modo monocromático, baixa visão.

→ Cor + ícone + texto (ex: ✓ Sucesso, ⚠ Aviso)

Ferramentas

Validação contínua

axe DevTools

Auditoria automatizada no browser. Detecta ~57% das issues.

Lighthouse

Score de acessibilidade integrado ao Chrome DevTools.

NVDA / VoiceOver

Teste real com leitor de tela. Insubstituível.

Teclado apenas

Desconectar mouse e completar tarefa. Detecta trap, ordem ilógica.