O que Auditoria de Acessibilidade faz?
Nome: a11y-audit Nível: PADRÃO Categoria: Engenharia - Qualidade Frontend Dependências: Python 3.8+ (Apenas Biblioteca Padrão) Autor: Alireza Rezvani Versão: 2.1.2 Última Atualização: 2026-03-18 Licença: MIT
Nome
a11y-audit -- Habilidade de Auditoria e Remediação de Acessibilidade WCAG 2.2
Descrição
A habilidade a11y-audit fornece um pipeline completo de auditoria de acessibilidade para aplicações web modernas. Ela implementa um fluxo de trabalho em três fases -- Escanear, Corrigir, Verificar -- que identifica violações WCAG 2.2 Níveis A e AA, gera correções de código exatas por framework e produz relatórios de conformidade prontos para stakeholders.
Esta habilidade vai além da detecção. Para cada violação encontrada, ela fornece a correção de código antes/depois precisa, adaptada ao seu framework (React, Next.js, Vue, Angular, Svelte ou HTML puro). Ela entende que um atributo alt ausente em um <img> no JSX do React requer um padrão de correção diferente do mesmo problema em um SFC Vue ou um template Angular.
O que esta habilidade faz:
- Escaneia sua base de código em busca de todas as violações WCAG 2.2 Níveis A e AA, categorizadas por severidade (Crítica, Grave, Leve)
- Corrige cada violação com padrões de código antes/depois específicos do framework
- Verifica se as correções resolvem as violações originais e não introduzem regressões
- Relata as descobertas em um formato estruturado adequado para desenvolvedores, gerentes de produto e stakeholders de conformidade
- Integra pipelines CI/CD para prevenir regressões de acessibilidade
Principais diferenciais:
- Padrões de correção com consciência de framework (não conselhos HTML genéricos)
- Análise de contraste de cores com sugestões de alternativas acessíveis
- Cobertura WCAG 2.2 incluindo os critérios de sucesso mais recentes (Aparência do Foco, Movimentos de Arrasto, Tamanho do Alvo)
- Integração com pipelines CI/CD via GitHub Actions, GitLab CI e Azure DevOps
- Suporte a comando slash via
/a11y-audit
Funcionalidades
Capacidades Principais
| Funcionalidade | Descrição |
|---|---|
| Escaneamento Completo WCAG 2.2 | Verifica todos os critérios de sucesso Nível A e AA em sua base de código |
| Detecção de Framework | Detecta automaticamente React, Next.js, Vue, Angular, Svelte ou HTML puro |
| Classificação de Severidade | Categoriza cada violação como Crítica, Grave ou Leve |
| Geração de Código de Correção | Produz diffs de código antes/depois para cada problema |
| Verificador de Contraste de Cores | Valida pares de primeiro plano/fundo contra taxas AA e AAA |
| Alternativas Acessíveis | Sugere cores de substituição que atendem aos requisitos de contraste |
| Relatório de Conformidade | Gera relatórios para stakeholders com resumos de aprovação/reprovação |
| Integração CI/CD | Configurações de pipeline para GitHub Actions, GitLab CI, Azure DevOps |
| Auditoria de Navegação por Teclado | Detecta problemas de gerenciamento de foco e ordem de tabulação ausentes |
| Validação ARIA | Verifica atributos ARIA incorretos, redundantes ou ausentes |
| Detecção de Regiões Vivas | Identifica conteúdo dinâmico sem anúncios aria-live |
| Acessibilidade de Formulários | Valida associações de rótulos, mensagens de erro e tipos de entrada |
Matriz de Cobertura WCAG 2.2
| Princípio | Critérios Nível A | Critérios Nível AA |
|---|---|---|
| Perceptível | 1.1.1 Conteúdo Não Textual, 1.2.1-1.2.3 Mídia Baseada em Tempo, 1.3.1-1.3.3 Adaptável, 1.4.1-1.4.2 Discernível | 1.3.4-1.3.5 Adaptável, 1.4.3-1.4.5 Contraste e Imagens de Texto, 1.4.10-1.4.13 Refluxo e Conteúdo |
| Operável | 2.1.1-2.1.2 Teclado, 2.2.1-2.2.2 Tempo, 2.3.1 Apreensões, 2.4.1-2.4.4 Navegável, 2.5.1-2.5.4 Entrada | 2.4.5-2.4.7 Navegável, 2.4.11 Aparência do Foco (NOVO 2.2), 2.5.7 Arrasto (NOVO 2.2), 2.5.8 Tamanho do Alvo (NOVO 2.2) |
| Compreensível | 3.1.1 Idioma, 3.2.1-3.2.2 Previsível, 3.3.1-3.3.2 Assistência de Entrada | 3.1.2 Idioma de Partes, 3.2.3-3.2.4 Previsível, 3.3.3-3.3.4 Tratamento de Erros, 3.3.7 Entrada Redundante (NOVO 2.2), 3.3.8 Autenticação Acessível (NOVO 2.2) |
| Robusto | 4.1.2 Nome/Função/Valor | 4.1.3 Mensagens de Status |
Definições de Severidade
| Severidade | Definição | Exemplo | SLA |
|---|---|---|---|
| Crítica | Bloqueia o acesso para grupos inteiros de usuários | Texto alternativo ausente em imagens informativas, sem acesso por teclado à navegação principal | Corrigir antes do lançamento |
| Grave | Barreira significativa que degrada a experiência | Contraste de cor insuficiente no texto do corpo, rótulos de formulário ausentes | Corrigir na sprint atual |
| Leve | Problema de usabilidade que causa atrito | Papéis ARIA redundantes, hierarquia de cabeçalhos abaixo do ideal | Corrigir nas próximas 2 sprints |
Uso
Início Rápido
Ative a habilidade e execute uma auditoria em seu projeto:
# Escanear projeto inteiro
python scripts/a11y_scanner.py /caminho/para/projeto
# Escanear com saída JSON para ferramentas
python scripts/a11y_scanner.py /caminho/para/projeto --json
# Verificar contraste de cores para valores específicos
python scripts/contrast_checker.py --fg "#777777" --bg "#ffffff"
# Verificar contraste em um arquivo CSS/Tailwind
python scripts/contrast_checker.py --file /caminho/para/styles.css
Comando Slash
Use o comando slash /a11y-audit para uma sessão de auditoria interativa:
/a11y-audit # Auditar projeto atual
/a11y-audit --scope src/ # Auditar diretório específico
/a11y-audit --fix # Auditar e aplicar correções automaticamente
/a11y-audit --report # Gerar relatório para stakeholders
/a11y-audit --ci # Saída de resultados compatível com CI
Fluxo de Trabalho em Três Fases
Fase 1: Escaneamento
O scanner percorre sua árvore de origem, detecta o framework em uso e aplica o conjunto de regras apropriado.
python scripts/a11y_scanner.py /caminho/para/projeto --format table
Exemplo de saída:
RELATÓRIO DE AUDITORIA A11Y - /caminho/para/projeto
Framework Detectado: React (Next.js)
Arquivos Escaneados: 127
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
CRÍTICAS (3 problemas)
[1.1.1] src/components/Hero.tsx:14
Texto alternativo ausente no elemento <img>
[2.1.1] src/components/Modal.tsx:8
Foco não preso dentro do diálogo modal
[1.4.3] src/styles/globals.css:42
Taxa de contraste 2.8:1 em .subtitle (requer 4.5:1)
GRAVES (7 problemas)
[2.4.11] src/components/Button.tsx:22
Indicador de foco não visível (contorno de 2px necessário)
[1.3.1] src/components/Form.tsx:31
Entrada sem <label> associado
...
LEVES (4 problemas)
[1.3.1] src/components/Nav.tsx:5
<nav> tem papel role="navigation" redundante
...
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
RESUMO: 14 violações (3 Críticas, 7 Graves, 4 Leves)
WCAG 2.2 Nível A: 8 problemas
WCAG 2.2 Nível AA: 6 problemas
Fase 2: Correção
Para cada violação, aplique a correção específica do framework. A habilidade fornece código antes/depois exato para cada tipo de problema.
Consulte a seção Padrões de Correção por Framework abaixo para o catálogo completo de correções.
Fase 3: Verificação
Reexecute o scanner para confirmar que todas as correções foram aplicadas e nenhuma regressão foi introduzida:
# Re-escanear após correções
python scripts/a11y_scanner.py /caminho/para/projeto --format table
# Comparar com a linha de base
python scripts/a11y_scanner.py /caminho/para/projeto --baseline audit-baseline.json
Saída de verificação:
RESULTADOS DA VERIFICAÇÃO
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Escaneamento Anterior: 14 violações (3 Críticas, 7 Graves, 4 Leves)
Escaneamento Atual: 2 violações (0 Críticas, 1 Grave, 1 Leve)
Resolvidas: 12 violações
Novos Problemas: 0 regressões
STATUS: MELHOROU (85,7% de redução)
Exemplos
Exemplo 1: Auditoria de Componente React
Dado um componente React com múltiplos problemas de acessibilidade:
// ANTES: src/components/ProductCard.tsx
function ProductCard({ product }) {
return (
<div onClick={() => navigate(`/product/${product.id}`)}>
<img src={product.image} />
<div style={{ color: '#aaa', fontSize: '12px' }}>
{product.name}
</div>
<span style={{ color: '#999' }}>${product.price}</span>
</div>
);
}
Violações detectadas:
| # | WCAG | Severidade | Problema |
|---|---|---|---|
| 1 | 1.1.1 | Crítica | <img> sem atributo alt |
| 2 | 2.1.1 | Crítica | <div onClick> não acessível por teclado |
| 3 | 1.4.3 | Grave | Cor #aaa em branco falha no contraste (2.32:1, necessário 4.5:1) |
| 4 | 1.4.3 | Grave | Cor #999 em branco falha no contraste (2.85:1, necessário 4.5:1) |
| 5 | 4.1.2 | Grave | Elemento interativo sem papel e nome acessível |
// DEPOIS: src/components/ProductCard.tsx
function ProductCard({ product }) {
return (
<a
href={`/product/${product.id}`}
className="product-card"
aria-label={`Ver ${product.name} - $${product.price}`}
>
<img src={product.image} alt={product.imageAlt || product.name} />
<div style={{ color: '#595959', fontSize: '12px' }}>
{product.name}
</div>
<span style={{ color: '#767676' }}>${product.price}</span>
</a>
);
}
O que mudou:
<div onClick>substituído por<a href>para suporte nativo a teclado e leitores de tela- Atributo
altadicionado ao<img>com fallback significativo aria-labelfornece contexto completo para tecnologia assistiva- Cor
#aaasubstituída por#595959(taxa de contraste 7.01:1 -- passa AA e AAA) - Cor
#999substituída por#767676(taxa de contraste 4.54:1 -- passa AA)
Exemplo 2: Auditoria de Formulário Vue SFC
<!-- ANTES: src/components/LoginForm.vue -->
<template>
<form @submit="handleLogin">
<input type="text" placeholder="Email" v-model="email" />
<input type="password" placeholder="Senha" v-model="password" />
<div v-if="error" style="color: red">{{ error }}</div>
<div @click="handleLogin">Entrar</div>
</form>
</template>
Violações detectadas:
| # | WCAG | Severidade | Problema |
|---|---|---|---|
| 1 | 1.3.1 | Crítica | Entradas sem elementos <label> associados |
| 2 | 3.3.2 | Grave | Texto do placeholder usado como único rótulo (desaparece ao digitar) |
| 3 | 2.1.1 | Crítica | <div @click> não acessível por teclado |
| 4 | 4.1.3 | Grave | Mensagem de erro não anunciada para leitores de tela |
| 5 | 3.3.1 | Grave | Erro não associado programaticamente à entrada |
<!-- DEPOIS: src/components/LoginForm.vue -->
<template>
<form @submit.prevent="handleLogin" aria-label="Acesse sua conta">
<div class="field">
<label for="login-email">Email</label>
<input
id="login-email"
type="email"
v-model="email"
autocomplete="email"
required
:aria-describedby="emailError ? 'email-error' : undefined"
:aria-invalid="!!emailError"
/>
<span v-if="emailError" id="email-error" role="alert">
{{ emailError }}
</span>
</div>
<div class="field">
<label for="login-password">Senha</label>
<input
id="login-password"
type="password"
v-model="password"
autocomplete="current-password"
required
:aria-describedby="passwordError ? 'password-error' : undefined"
:aria-invalid="!!passwordError"
/>
<span v-if="passwordError" id="password-error" role="alert">
{{ passwordError }}
</span>
</div>
<div v-if="error" role="alert" aria-live="assertive" class="form-error">
{{ error }}
</div>
<button type="submit">Entrar</button>
</form>
</template>
Exemplo 3: Auditoria de Template Angular
<!-- ANTES: src/app/dashboard/dashboard.component.html -->
<div class="tabs">
<div *ngFor="let tab of tabs"
(click)="selectTab(tab)"
[class.active]="tab.active">
{{ tab.label }}
</div>
</div>
<div class="tab-content">
<div *ngIf="selectedTab">{{ selectedTab.content }}</div>
</div>
Violações detectadas:
| # | WCAG | Severidade | Problema |
|---|---|---|---|
| 1 | 4.1.2 | Crítica | Widget de abas sem papéis ARIA (tablist, tab, tabpanel) |
| 2 | 2.1.1 | Crítica | Abas não navegáveis por teclado (setas, Home, End) |
| 3 | 2.4.11 | Grave | Nenhum indicador de foco visível na aba ativa |
<!-- DEPOIS: src/app/dashboard/dashboard.component.html -->
<div class="tabs" role="tablist" aria-label="Seções do painel">
<button
*ngFor="let tab of tabs; let i = index"
role="tab"
[id]="'tab-' + tab.id"
[attr.aria-selected]="tab.active"
[attr.aria-controls]="'panel-' + tab.id"
[attr.tabindex]="tab.active ? 0 : -1"
(click)="selectTab(tab)"
(keydown)="handleTabKeydown($event, i)"
class="tab-button"
[class.active]="tab.active">
{{ tab.label }}
</button>
</div>
<div
*ngIf="selectedTab"
role="tabpanel"
[id]="'panel-' + selectedTab.id"
[attr.aria-labelledby]="'tab-' + selectedTab.id"
tabindex="0"
class="tab-content">
{{ selectedTab.content }}
</div>
TypeScript de suporte para navegação por teclado:
// dashboard.component.ts
handleTabKeydown(event: KeyboardEvent, index: number): void {
const tabCount = this.tabs.length;
let newIndex = index;
switch (event.key) {
case 'ArrowRight':
newIndex = (index + 1) % tabCount;
break;
case 'ArrowLeft':
newIndex = (index - 1 + tabCount) % tabCount;
break;
case 'Home':
newIndex = 0;
break;
case 'End':
newIndex = tabCount - 1;
break;
default:
return;
}
event.preventDefault();
this.selectTab(this.tabs[newIndex]);
// Mover foco para o botão da nova aba
const tabElement = document.getElementById(`tab-${this.tabs[newIndex].id}`);
tabElement?.focus();
}
Exemplo 4: Auditoria de Página Next.js
// ANTES: src/app/page.tsx
export default function Home() {
return (
<main>
<div className="text-4xl font-bold">Bem-vindo à Acme</div>
<div className="mt-4">
Construa produtos melhores com nossa plataforma.
</div>
<div className="mt-8 bg-blue-600 text-white px-6 py-3 rounded cursor-pointer"
onClick={() => router.push('/signup')}>
Começar
</div>
</main>
);
}
Violações detectadas:
| # | WCAG |
...