FM

Auditoría de Accesibilidad WCAG 2.2

FlowMetrics SaaS — Dashboard de Operaciones Logísticas

Nivel objetivo: AA
6
Críticos
4
Mayores
3
Menores
5
Conformes
13/18
SC Auditados
Cliente: FlowMetrics Inc. Fecha auditoría: 18 jun 2026 Stack: React 18 · Tailwind CSS · Recharts Estándar: WCAG 2.2 AA Auditado por: CULTIVA IA · Web Accesibilidad
📊

Puntuación por principios POUR

42%
Perceptible
Contraste, texto alt, reflow
Falla
55%
Operable
Teclado, foco, target size
Falla
70%
Comprensible
Errores, consistencia, idioma
Parcial
85%
Robusto
ARIA, semántica, AT compat.
Pasa
⚠️ Veredicto actual: NO CONFORME AA. Se han detectado 6 criterios de éxito críticos que bloquean el acceso a usuarios de lectores de pantalla y navegación por teclado. Se requieren correcciones antes de certificar la plataforma para clientes Enterprise.
🎨

Hallazgos — Percepción

● Crítico

Contraste insuficiente en texto secundario y métricas de KPI

Dashboard principal · Tarjetas KPI · Tabla de pedidos

SC 1.4.3
Descripción del problema

El texto de labels y valores secundarios (#9CA3AF sobre #1A1D27) presenta una ratio de contraste de 3.2:1, por debajo del mínimo de 4.5:1 exigido por WCAG 2.2 SC 1.4.3 para texto normal. Afecta a ~60% del contenido informativo del dashboard.

Análisis de contraste
#9CA3AF
sobre fondo
3.2:1
#9CA3AF / #1A1D27
✗ Falla AA
Texto mejorado
#C4C9E2
7.1:1
#C4C9E2 / #1A1D27
✓ Pasa AAA
Alerta roja
#EF4444
5.9:1
#EF4444 / #1A1D27
✓ Pasa AA
Placeholder
#6B7280
2.4:1
#6B7280 / #22263A
✗ Falla AA
Corrección (Tailwind CSS)
✗ Actual
<p className="text-gray-400">
  Pedidos hoy
</p>
<span className="text-sm
  text-gray-500">
  vs ayer
</span>
✓ Corregido
<p className="text-slate-300">
  Pedidos hoy
</p>
<span className="text-sm
  text-slate-400">
  vs ayer
</span>
◆ Mayor

Gráficos de rendimiento sin alternativa textual

Dashboard · Recharts LineChart, BarChart

SC 1.1.1
Descripción del problema

Los gráficos SVG generados por Recharts carecen de aria-label, role="img" y <title>. Un usuario de lector de pantalla solo escucha "group" sin contexto alguno. Los datos del gráfico son críticos para la toma de decisiones.

Corrección — wrapper accesible para Recharts
✗ Actual
<LineChart
  data={shipmentData}
  width={500}
  height={300}
>
  ...
</LineChart>
✓ Corregido
<div
  role="img"
  aria-label="Envíos diarios
    jun 2026: pico 1.240
    el día 12"
>
  <LineChart ...>...
  /* tabla de datos oculta */
  <table className="sr-only">
    ...
  </table>
</div>
⌨️

Hallazgos — Operabilidad

● Crítico

Botón "Exportar CSV" sin etiqueta accesible (icono-only)

Dashboard · Barra de acciones superiores

SC 4.1.2
Descripción del problema

El botón de exportación muestra únicamente un icono SVG sin aria-label. NVDA/VoiceOver anuncia "botón" sin nombre descriptivo. Además, el SVG carece de aria-hidden="true", por lo que el lector intenta leer el contenido vectorial.

Corrección
✗ Actual
<button
  onClick={exportCSV}
  className="btn-icon"
>
  <DownloadIcon />
</button>
✓ Corregido
<button
  onClick={exportCSV}
  aria-label="Exportar datos
    a CSV"
  className="btn-icon"
>
  <DownloadIcon
    aria-hidden="true"
    focusable="false"
  />
</button>
● Crítico

Modal de filtros sin trampa de foco (focus trap)

Modal de filtros avanzados · Overlay

SC 2.1.2
Descripción del problema

Al abrir el modal de filtros avanzados, el foco del teclado puede escapar al contenido de fondo. WCAG 2.2 SC 2.1.2 exige que el foco quede contenido dentro del modal y sea liberado mediante la tecla Escape o un botón de cierre explícito. Además, al cerrar, el foco no retorna al botón que lo abrió.

Corrección — Focus Trap con React
✗ Actual (sin focus trap)
function FilterModal() {
  return (
    <div className="modal">
      <form>...</form>
    </div>
  );
}
✓ Corregido
import FocusTrap
  from 'focus-trap-react';

function FilterModal({ onClose }) {
  return (
    <FocusTrap
      focusTrapOptions={{
        returnFocusOnDeactivate: true,
        escapeDeactivates: true
      }}
    >
      <div
        role="dialog"
        aria-modal="true"
        aria-labelledby="modal-title"
      >
        <form>...</form>
      </div>
    </FocusTrap>
  );
}
◦ Menor

Botones de acción en tabla inferiores a 24×24 CSS px

Tabla de pedidos recientes · Columna "Acciones"

SC 2.5.8
Descripción del problema

Los botones de editar/eliminar en la columna de acciones miden 18×18 px. WCAG 2.2 introdujo SC 2.5.8 Target Size (Minimum) que exige un área mínima de 24×24 CSS pixels o espacio adicional equivalente (offset) para no solapar con otros objetivos.

Corrección — aumentar área de clic sin cambiar diseño
✗ Actual
.action-btn {
  width: 18px;
  height: 18px;
  padding: 0;
}
✓ Corregido
.action-btn {
  /* Icono visual */
  width: 18px;
  height: 18px;
  /* Área táctil 24×24 */
  padding: 3px;
  min-width: 24px;
  min-height: 24px;
}
📋

Hallazgos — Comprensibilidad y Robustez

◆ Mayor

Tabla de pedidos sin encabezados semánticos <th>

Dashboard · Tabla "Pedidos recientes"

SC 1.3.1
Descripción del problema

La tabla usa únicamente <div> con estilos CSS para simular una tabla. Los lectores de pantalla no pueden asociar datos con sus encabezados ni anunciar la posición de la celda. SC 1.3.1 (Info and Relationships) exige que la estructura lógica sea perceptible programáticamente.

Corrección
✗ Actual (div-table)
<div className="table">
  <div className="row header">
    <div>ID</div>
    <div>Estado</div>
    <div>Importe</div>
  </div>
</div>
✓ Corregido (HTML semántico)
<table>
  <caption
    className="sr-only">
    Pedidos recientes
  </caption>
  <thead>
    <tr>
      <th scope="col">ID</th>
      <th scope="col">Estado</th>
      <th scope="col">Importe</th>
    </tr>
  </thead>
</table>
◆ Mayor

Banner de alerta crítica comunica estado solo por color

Banner sistema · Indicadores de estado en tabla

SC 1.4.1
Descripción del problema

El banner de "Sistema degradado" usa únicamente un fondo rojo para indicar criticidad. SC 1.4.1 prohíbe usar el color como único medio de transmitir información. Los usuarios con deuteranopia o protanopia no pueden distinguir el estado. Además, el banner carece de role="alert" para que los lectores de pantalla lo anuncien automáticamente.

Corrección
✗ Actual
<div className="bg-red-600
  text-white p-3">
  Sistema degradado
</div>
✓ Corregido
<div
  role="alert"
  aria-live="assertive"
  className="bg-red-600
    text-white p-3
    border-l-4
    border-red-900"
>
  <span aria-hidden="true">
    ⚠️
  </span>
  <strong>CRÍTICO:</strong>
  Sistema degradado
</div>
🗺️

Hoja de ruta de correcciones

# Hallazgo Criterio Esfuerzo Sprint
1
Focus trap en modal de filtros
Bloquea 100% usuarios teclado
SC 2.1.2 Bajo (2h) S1
2
aria-label botones icono-only
4 botones afectados
SC 4.1.2 Bajo (1h) S1
3
Contraste texto secundario
Cambio global de design tokens
SC 1.4.3 Medio (4h) S1
4
Tabla HTML semántica
Refactor componente OrderTable
SC 1.3.1 Medio (3h) S2
5
role="alert" en banner de estado
+ indicador no-color
SC 1.4.1 Bajo (1h) S2
6
Alt textual para gráficos Recharts
Wrapper + tabla sr-only
SC 1.1.1 Medio (6h) S2
7
Target size 24×24px botones tabla
padding CSS, sin cambio visual
SC 2.5.8 Bajo (30m) S3
Estimación total: ~17,5h de desarrollo · 2-3 sprints para cumplimiento AA completo

Checklist de validación post-corrección

Contraste mínimo 4.5:1 en todo texto de tamaño normal (verificar con axe DevTools)
Todos los botones icono-only tienen aria-label descriptivo
Modal de filtros atrapa el foco y lo libera con Escape + retorna al trigger
Tabla de pedidos usa <th scope="col"> y <caption> semántico
Gráficos tienen role="img" + aria-label con resumen de datos
Banner de alerta tiene role="alert" y usa icono + texto además del color
Botones de acción ≥ 24×24 CSS px (target size SC 2.5.8)
Indicador de foco visible en todos los elementos interactivos (Tailwind focus-visible)
Idioma del documento declarado: <html lang="es">
Formularios tienen <label> asociado a cada input (for/id)
Navegación principal accesible por teclado (tab order lógico)
No hay trampas de teclado fuera de modales
Ejecutar auditoría automatizada con axe-core CI (zero violations críticas)
Prueba manual con NVDA + Chrome y VoiceOver + Safari en los 5 flujos críticos
Verificar reflow al 400% de zoom sin scroll horizontal (SC 1.4.10)
Herramientas recomendadas para validación:

axe DevTools — auditoría automática en CI/CD  ·  WAVE — extensión de navegador  ·  Colour Contrast Analyser — ratios precisos  ·  NVDA + Chrome — prueba lectores pantalla Windows  ·  VoiceOver + Safari — prueba macOS/iOS  ·  Lighthouse — integración Vercel/CI