Por que Acessibilidade não é sobre "marcar caixinhas", mas sobre pessoas
Sejamos honestos: quando ouvimos "acessibilidade" (ou a11y), muitos de nós imaginamos listas intermináveis de requisitos, verificações chatas e a frase "bem, isso é para pessoas com deficiências". Mas a verdade é que acessibilidade é sobre todos. Você já tentou pedir uma pizza andando, segurando o telefone com uma mão? Ou ficou no metrô com internet ruim, onde o site carregava por horas? Esses são problemas de acessibilidade.
Neste artigo, falaremos sobre como o TypeScript pode se tornar seu melhor amigo na criação de aplicações web acessíveis. Não apenas "adicionar tags", mas construir uma arquitetura onde a inclusividade não é um recurso, mas um fundamento.
TypeScript como escudo contra erros de a11y
Muitos pensam que TypeScript é apenas sobre tipos de dados e proteção contra bugs. Mas, na verdade, a tipagem estrita também pode salvar em questões de acessibilidade. Vamos analisar com exemplos.
Tipagem de atributos ARIA
Um dos problemas mais comuns são valores incorretos de atributos ARIA. Você já escreveu role="button" em uma div? E depois esqueceu de adicionar tabindex? O TypeScript pode detectar isso em tempo de compilação.
// Ruim: nenhuma proteçãofunction createButton(label: string) { return `<div role="button">${label}</div>`;}
// Bom: tipando ARIAtype AriaRole = 'button' | 'navigation' | 'alert' | 'dialog';
interface AriaAttributes { role: AriaRole; 'aria-label'?: string; 'aria-expanded'?: boolean; tabIndex?: number;}
function createAccessibleButton(label: string, aria: AriaAttributes) { // Agora o TypeScript verificará se o role é válido return { tag: 'div', attrs: aria, content: label };}
// Erro! 'btn' não está no tipo AriaRole// createAccessibleButton('Clique em mim', { role: 'btn' });Sente a diferença? O TypeScript não deixará você escrever acidentalmente role="btutton" ou esquecer um atributo obrigatório. É como um assistente pessoal que sussurra: "Ei, tem certeza de que isso é acessível?"
Verificação rigorosa de estados de foco
Outra dor de cabeça é o gerenciamento de foco. Especialmente em SPAs, onde a página não recarrega. O TypeScript ajuda a criar wrappers seguros.
// Definindo quais elementos podem receber focotype FocusableElement = HTMLInputElement | HTMLButtonElement | HTMLAnchorElement | HTMLSelectElement | HTMLTextAreaElement;
function safelySetFocus(element: FocusableElement | null): void { if (element && document.contains(element)) { element.focus(); } else { console.warn('Elemento não encontrado no DOM ou não pode receber foco'); }}
// Usoconst modal = document.querySelector('.modal__close-btn');safelySetFocus(modal as FocusableElement | null);Observe: não estamos apenas chamando .focus(), mas verificando se o elemento existe e pode ser focado. Isso previne erros que podem deixar o usuário de leitor de tela no vazio.
Construindo arquitetura com a11y na base
Agora vamos para coisas mais avançadas. Como fazer com que a acessibilidade esteja embutida na arquitetura do seu projeto, e não adicionada "de última hora" antes do lançamento?
Props tipadas para componentes
Crie uma interface base para todos os seus componentes. É como uma constituição para a acessibilidade.
// Interface base para todos os componentes de UIinterface AccessibleComponentProps { id?: string; className?: string; ariaLabel?: string; ariaDescribedby?: string; role?: string; tabIndex?: number; isDisabled?: boolean; onClick?: () => void; onKeyDown?: (e: React.KeyboardEvent) => void;}
// Componente de botão específicointerface ButtonProps extends AccessibleComponentProps { variant