Product Craft Bible
Modals & Overlays
Inicio Componentes UI Modals & Overlays
Componentes UI

Modals & Overlays

12 reglas WAI-ARIA APG, Dialog (Modal) Pattern · WCAG 2.1.2Adrian Roselli, 'Where to Put Focus When Opening a Modal Dialog' (junio 2025)WAI-ARIA APG Dialog Pattern · WCAG 2.5.5 · Apple HIGMaterial Design 3, Dialogs (m3.material.io/components/dialogs/guidelines)
161

Modals & Overlays

12 reglas
1379

Trap de foco dentro del dialog; devuelve foco al cerrar

Cuando un modal abre, Tab y Shift+Tab deben ciclar solo entre los elementos enfocables del dialog, envolviendo en ambos extremos. Al cerrar, el foco regresa programáticamente al elemento disparador. Requerido por WCAG 2.1.2.

WAI-ARIA APG, Dialog (Modal) Pattern · WCAG 2.1.2
Preferir

Eliminar cuenta

Esta accion es permanente y no puede deshacerse.

Tab cicla: Cancelar → Eliminar → Cancelar
Esc cierra y devuelve foco al boton disparador

1380

Foco inicial segun tipo de contenido, no siempre el primer campo

En dialogs destructivos o inesperados, focaliza el heading o el boton menos destructivo. En dialogs informativos breves, focaliza el boton de cerrar. Solo focaliza el primer input cuando el usuario abrio intencionalmente un formulario corto y familiar.

Adrian Roselli, 'Where to Put Focus When Opening a Modal Dialog' (junio 2025)
Preferir

¿Publicar en produccion?

Evitar

¿Publicar en produccion?

1381

Boton de cierre visible con target minimo de 44x44 px

Todo dialog debe incluir al menos un boton visible que lo cierre, independiente del soporte de Escape. El area clickeable minima es 44x44 px segun WCAG 2.5.5 y Apple HIG; el icono puede ser de 16 px dentro de ese contenedor.

WAI-ARIA APG Dialog Pattern · WCAG 2.5.5 · Apple HIG
Preferir

Confirmacion enviada

Area 44x44 px
Evitar

Confirmacion enviada

1382

Ancho maximo de 560 px en desktop; pantalla completa bajo 600 px

Material Design 3 especifica max-width: 560 dp. Por debajo de 600 dp (movil portrait) el dialog debe pasar a presentacion full-screen para mantener margenes de lectura comodos y targets tactiles adecuados.

Material Design 3, Dialogs (m3.material.io/components/dialogs/guidelines)
Preferir

Confirmar pago

Total: $4,500 MXN

Evitar

Confirmar pago

Total: $4,500 MXN

1383

Usa role='alertdialog' y focaliza el mensaje en prompts urgentes

Cuando el dialog requiere respuesta inmediata (vencimiento de sesion, confirmacion destructiva), usa role='alertdialog' con aria-labelledby apuntando al titulo y aria-describedby al cuerpo. Los lectores de pantalla anuncian el contenido inmediatamente al abrir.

WAI-ARIA spec, alertdialog role · MDN Web Docs
Preferir

Sesion por expirar

Tu sesion expirara en 5 minutos. Guarda tu trabajo o extiende la sesion.

role="alertdialog" anuncia titulo + cuerpo inmediatamente

1384

Toast: auto-dismiss minimo 4 s; siempre ofrecer cierre manual

Toasts con auto-dismiss deben permanecer visibles al menos 4 segundos. Escala ~1 s por cada 3 palabras adicionales sobre base de 5 palabras. Los toasts de error nunca deben auto-cerrarse. Usa role='status' y aria-live='polite'.

Material Design, Snackbars · WCAG 2.2.1 · Scott O'Hara, a11y toasts
Preferir
Archivo guardado

Persiste 5 s · cierre manual disponible

Evitar

Tu sesion ha expirado. Por favor inicia sesion de nuevo para continuar.

Cerrando en 2 s...

1385

Dialogs de confirmacion solo para acciones irreversibles o de alto costo

Las confirmaciones repetidas para acciones de bajo riesgo producen desensibilizacion tipo "cry wolf": el usuario hace clic sin leer. Reserva el dialog para destruccion de datos, gasto significativo o acciones que no se pueden deshacer. Los labels de botones deben describir el resultado, no "Si / No".

Nielsen Norman Group, 'Confirmation Dialogs Can Prevent User Errors (If Not Overused)'
Preferir

Eliminar espacio de trabajo

Todos los proyectos y miembros seran eliminados permanentemente.

Evitar

¿Estas seguro?

1386

Scrim de 40-50% de opacidad negra; nunca opacidad total

El overlay detras del modal debe usar negro a 40-50% de opacidad. Mas oscuro del 60% desorienta al quitar contexto espacial; mas claro del 25% falla en indicar que el fondo esta bloqueado. En browsers modernos, backdrop-filter: blur(4px) con 20-30% es una alternativa elegante.

Material Design 3 scrim token · Nielsen Norman Group, Bottom Sheets
Preferir

Scrim 45%

Contenido dimmed pero visible

Evitar

Scrim 90%

Contexto de pagina invisible

1387

No uses modal dialogs para informacion no bloqueante de baja urgencia

El costo de un modal es la interrupcion de la tarea actual. Solo se justifica cuando falta informacion requerida, se va a ejecutar una accion irreversible, o un error bloquea el progreso. Para mensajes informativos usa toast, banner, o panel lateral.

Nielsen Norman Group, 'Modal & Nonmodal Dialogs: When (& When Not) to Use Them'
Preferir
Exportacion lista, Descargar
Evitar

Suscribete al newsletter

Solo las mejores noticias

Aparece 1 s despues de cargar la pagina

1388

Outside-click cierra dialogs transitorios; bloquea en confirmaciones destructivas

Date pickers, menus y selectores deben cerrarse al hacer clic en el scrim. Los dialogs de confirmacion destructiva y formularios con datos sin guardar no deben cerrarse con outside-click; requieren una accion explicita de Cancelar. Radix UI AlertDialog desactiva esto por disenio.

Radix UI, AlertDialog vs Dialog primitives · Nielsen Norman Group modal guidelines
Preferir

Eliminar proyecto

Esta accion no puede deshacerse

Clic exterior bloqueado

Clic exterior cierra

Evitar

Editar direccion de facturacion

Clic en el fondo = datos perdidos silenciosamente

1389

Usa el elemento nativo <dialog> con showModal() sobre implementaciones ARIA manuales

<dialog> + showModal() provee focus trap, Escape, semantica aria-modal, renderizado en top-layer y ::backdrop de forma nativa. Elimina la necesidad de librerias JS y evita los tres bugs mas comunes: z-index, overflow:hidden y transforms ancestros.

MDN Web Docs, <dialog> element · web.dev, 'Popover and dialog' · Adrian Roselli
Preferir
<dialog id="modal">
  ...contenido...
</dialog>

modal.showModal();

✓ Top-layer nativo, sobre todo

✓ Focus trap integrado

✓ ::backdrop sin DOM extra

Evitar
<div role="dialog"
  aria-modal="true"
  style="z-index:9999">
</div>

✗ Clips bajo ancestors con overflow:hidden

✗ Requiere libreria focus-trap

✗ Bugs de z-index con date pickers

1390

Nunca apiles multiples modals; usa un solo dialog con revelacion progresiva

Un segundo modal sobre uno activo crea focus traps anidados, ambiguedad en Escape, y confusion de scrim. Apple HIG y Nielsen Norman Group lo prohiben explicitamente. Si se necesita un sub-paso, reemplaza el contenido del mismo dialog en su lugar con indicador de progreso.

Apple HIG, Modality · Nielsen Norman Group, Bottom Sheets
Preferir
1
2

Seleccionar plantilla

Paso 1 de 2, el contenido del dialog se reemplaza, no se apila

Plantilla A

Plantilla B

Evitar

Agregar miembro

Crear nuevo rol

Usuario no sabe cuantas capas hay