Skip to content

Accesibilidad en React

React no hace una interfaz accesible por si solo. Ayuda a componer UI, pero la semantica, foco, teclado y estados ARIA siguen siendo responsabilidad del desarrollador.

Semantica primero

Usa elementos HTML correctos:

tsx
<button onClick={save}>Guardar</button>

Mejor que:

tsx
<div onClick={save}>Guardar</div>

Un button ya soporta foco, teclado y semantica.

Labels

tsx
<label htmlFor="email">Email</label>
<input id="email" name="email" type="email" />

Sin label, usuarios de lector de pantalla pierden contexto.

Errores de formulario

tsx
<input
  id="email"
  aria-invalid={Boolean(error)}
  aria-describedby={error ? "email-error" : undefined}
/>
{error && <p id="email-error">{error}</p>}

Gestion de foco

Al abrir un modal:

  • Mueve foco al modal.
  • Atrapa foco dentro.
  • Cierra con Escape.
  • Devuelve foco al disparador al cerrar.

Para componentes complejos, considera librerias accesibles como Radix UI, React Aria o Headless UI.

Teclado

Todo flujo importante debe poder usarse sin raton.

Comprueba:

  • Tab.
  • Shift + Tab.
  • Enter.
  • Space.
  • Escape.
  • Flechas en menus/tabs si aplica.

Estados visibles

No elimines outline sin reemplazo claro.

css
:focus-visible {
  outline: 2px solid #2563eb;
  outline-offset: 2px;
}

ARIA

ARIA complementa semantica, no la sustituye.

Regla:

txt
Si puedes usar HTML nativo, usa HTML nativo.

Live regions

Para mensajes dinamicos:

tsx
<p role="status" aria-live="polite">
  Producto guardado
</p>

Testing de accesibilidad

Herramientas:

  • Testing Library.
  • axe.
  • Lighthouse.
  • Navegacion con teclado.
  • Lector de pantalla en flujos criticos.

Ejemplo:

tsx
screen.getByRole("button", { name: /guardar/i })

Buscar por role fuerza una UI mas accesible.

Buenas practicas

  • Usa HTML semantico.
  • No construyas botones con div.
  • Prueba teclado.
  • Gestiona foco en modales, drawers y menus.
  • Asocia errores con campos.
  • Usa librerias accesibles para patrones complejos.