Un alert dialog es un cuadro de diálogo modal que interrumpe el flujo de trabajo del usuario para comunicarle un mensaje importante que requiere una respuesta inmediata (por ejemplo, confirmar una acción destructiva o avisar de un error grave). Al aplicar el rol alertdialog
, las tecnologías asistivas y los navegadores pueden tratarlo de forma especial (p. ej., reproducir un sonido de sistema), diferenciándolo de otros diálogos convencionales.
En el apartado de Ejemplo de implementación podréis ver un ejemplo de implementación de un alert dialog en React.
Estructura semántica mínima
- El contenedor nativo
<dialog>
aporta toda la sintaxis semántica que necesita un modal. En casos de necesidad, se puede extender la semántica utilizandorole="alertdialog"
. También podría utilizarse un<div>
, pero requerirá más trabajo. - Deberá tener un título visible y referenciado con
aria-labelledby
, para proporcionarle un nombre accesible. - Deberá tener un texto del mensaje y referenciado con
aria-describedby
, para proporcionarle una descripción accesible. - Deberá tener botones de acción que permitan responder al mensaje.
- El foco inicial se envía al botón menos destructivo.
El diálogo debe tener un título y un mensaje legibles para satisfacer el SC1 4.1.2 (Name, Role, Value).
Comportamiento de teclado y gestión del foco
Al abrir el diálogo
- Mueve el foco al primer control dentro del
<dialog>
. - Guarda la referencia del elemento que abrió el diálogo para restaurarlo al cerrar.
- Mueve el foco al primer control dentro del
Ciclo de tabulación
- Tab y Shift + Tab recorren solo los controles del diálogo (focus trap).
- Evita que el foco se “escape” accidentalmente (SC 2.1.2 No Keyboard Trap).
Salir con Esc
- Permite cerrar el diálogo con la tecla Esc y devuelve el foco al elemento que abrió el diálogo.
Visibilidad y orden de foco
- El foco debe seguir un orden lógico (SC 2.4.3 Focus Order) y ser visible (SC 2.4.7 Focus Visible; SC 2.4.11 Focus Not Obscured, nuevo en WCAG 2.2).
Operable solo con teclado
- Todas las acciones (aceptar, cancelar, cerrar) han de ser ejecutables mediante teclado (SC 2.1.1 Keyboard)
Criterios de éxito (SC) asociados al alert dialog
SC | Nombre | Cómo afecta a alertdialog | Nivel |
---|---|---|---|
2.1.1, se abrirá en una nueva pestaña | Keyboard | Toda funcionalidad operable por teclado | A |
2.1.2, se abrirá en una nueva pestaña | No Keyboard Trap2 | El foco no queda atrapado sin salida evidente | A |
2.4.3, se abrirá en una nueva pestaña | Focus Order | Secuencia de foco lógica dentro y fuera del diálogo | A |
2.4.7, se abrirá en una nueva pestaña | Focus Visible | Indicador de foco perceptible | AA |
2.4.11/12, se abrirá en una nueva pestaña | Focus Not Obscured | El elemento con foco no queda oculto por el diálogo ni por el overlay | AA/AAA |
4.1.2, se abrirá en una nueva pestaña | Name, Role, Value | role=“alertdialog”, aria-labelledby, aria-describedby | A |
4.1.3, se abrirá en una nueva pestaña | Status Messages | Si el diálogo informa de estado (p. ej. confirmación rápida), usa role=“alert” o alertdialog | AA |
Buenas prácticas complementarias
- Anunciar cambios breves (p. ej. “Notas guardadas”) con
role="alert"
en lugar dealertdialog
para no exigir interacción del usuario. No será necesario elrole="alert"
en caso de utilizar el elemento<dialog>
. - Mantén la jerarquía de encabezados y el orden DOM para que la secuencia de lectura sea lógica (SC 1.3.2 Meaningful Sequence, se abrirá en una nueva pestaña).
- Utiliza
role="document"
ytabindex="0"
en el contenedor del diálogo para que los lectores de pantalla puedan identificarlo como el contenido principal del elemento. - Minimiza el uso de ARIA. Utiliza el elemento
<dialog>
y su atributoopen
de preferencia; añaderole="alertdialog"
solo cuando sea necesario. - Prueba con lectores de pantalla (NVDA, JAWS, VoiceOver) y navegadores móviles.
Lista de verificación rápida
- El diálogo tiene título (
aria-labelledby
oaria-label
). - Hay descripción (
aria-describedby
) que se lee automáticamente. - Se abre mediante un control accesible.
- Foco inicial en la acción más segura; focus trap.
- Se cierra con Esc y devuelve el foco al elemento activador.
- Todos los botones son operables por teclado y muestran foco visible.
- El diálogo y su foco nunca quedan ocultos detrás de otros elementos.
Ejemplo de implementación
El diálogo tiene título y descripción
<dialog
role="alertdialog"
aria-labelledby="dialog-title"
aria-describedby="dialog-description"
...
>
...
<h2 id="dialog-title">...</h2>
<p id="dialog-description">...</p>
...
</dialog>
Se abre mediante un control accesible
const [isOpen, setIsOpen] = useState(false);
...
<button onClick={() => setIsOpen(true)}>Open dialog</button>
Foco inicial en la acción más segura; focus trap, se cierra con Esc y devuelve el foco al elemento activador.
const handleKeyDown = (event) => {
if (event.key === "Escape") {
setIsOpen(false);
}
};
const handleFocusTrap = (event) => {
if (!isOpen) return;
const dialog = dialogRef.current;
if (!dialog) return;
const focusableElements = dialog.querySelectorAll(
'button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])'
);
const firstFocusable = focusableElements[0];
const lastFocusable = focusableElements[focusableElements.length - 1];
if (event.key === "Tab") {
if (event.shiftKey && document.activeElement === firstFocusable) {
event.preventDefault();
lastFocusable.focus();
} else if (!event.shiftKey && document.activeElement === lastFocusable) {
event.preventDefault();
firstFocusable.focus();
}
}
};
useEffect(() => {
...
if (isOpen) {
...
} else {
triggerRef.current?.focus();
}
...
}, [isOpen]);
Soporte del elemento <dialog>
en navegadores
Footnotes
-
En los documentos de las Pautas de Accesibilidad para el Contenido Web (WCAG), la abreviatura SC significa Success Criterion (criterio de éxito). Cada criterio describe un requisito verificable que el contenido debe cumplir para alcanzar un determinado nivel de conformidad (A, AA o AAA). ↩
-
La “trampa de teclado” que prohíbe la WCAG 2.1.2 se refiere a quedar atrapado sin salida: si entras en un componente y después no existe ninguna forma de salir solo con el teclado, o necesitas combinaciones no estándar y nadie te las indica. La propia página de No Keyboard Trap (Level A), se abrirá en una nueva pestaña pone como ejemplo válido un diálogo modal cuya tabulación se mantiene dentro de él mientras esté abierto; la clave es que el usuario puede abandonarlo con un botón Cancelar/OK o con la tecla Esc. ↩