Planteamiento y contexto
Una consola de administración necesita una confirmación destructiva y un formulario de motivo. Algunos flujos deben cerrarse únicamente mediante una acción explícita; otros pueden cerrarse con Escape o un clic exterior. Diseñe la política de cierre del elemento dialog nativo para las rutas de teclado, táctiles y de validación.
MDN define los valores de closedby none, closerequest y any: solo mecanismos del desarrollador, solicitudes de cierre de la plataforma más mecanismos del desarrollador, o los tres mecanismos. Los diálogos modales usan showModal(); los diálogos no modales usan show().
Qué está evaluando el entrevistador
El candidato debe mapear el riesgo de negocio a la política de cierre, distinguir los diálogos modales de los popovers y explicar Escape, el descarte ligero (light dismiss), close(), requestClose(), method="dialog", el foco inicial, la restauración del foco y la validación de formularios.
Preguntas de clarificación para hacer primero
- ¿Puede descartarse accidentalmente una confirmación destructiva y deben conservarse los datos no guardados?
- ¿Escape o un clic exterior equivalen a cancelar, o requieren otra confirmación?
- ¿Debe un botón de cancelar omitir la validación de campos obligatorios?
- ¿Deben los navegadores no compatibles ofrecer un comportamiento de cierre idéntico?
- ¿A dónde debe regresar el foco cuando se cierra el diálogo?
Estructura de respuesta en 30 segundos
“Para acciones destructivas utilizo showModal() con closedby="closerequest", o none para la confirmación más estricta, además de botones explícitos de cancelar y confirmar. Un panel informativo de bajo riesgo puede usar any u popover="auto". Un formulario con method="dialog" devuelve un valor; un botón de cancelar puede usar formnovalidate cuando deba omitir la validación. Establezco un foco inicial intencional y restauro el foco al elemento activador. La detección de capacidades proporciona un fallback con botones explícitos y manejo manual del teclado.”
Análisis detallado paso a paso
Paso 1: Elegir entre modal o no modal
showModal() hace que el resto del documento sea inerte y se adapta a confirmaciones destructivas o tareas obligatorias. show() deja la página interactiva para un panel auxiliar. Alternar únicamente el atributo open no establece la semántica modal de foco ni de fondo.
Paso 2: Mapear el riesgo a closedby
closedby="none" solo permite el cierre definido por el desarrollador y es adecuado para confirmaciones irreversibles. closerequest también acepta Escape o una solicitud de cierre de la plataforma. any añade el descarte ligero por clic exterior y se adapta a información de bajo riesgo.
<dialog id="delete-dialog" closedby="closerequest">
<form method="dialog">
<button value="cancel">Cancel</button>
<button value="confirm">Delete</button>
</form>
</dialog>Paso 3: Manejar Escape, request-close y close
Escape o un gesto de la plataforma es una solicitud de cierre. requestClose() puede ejecutar la ruta de solicitud de cierre para que la aplicación pueda confirmarla o interceptarla. close() cierra directamente y puede establecer returnValue. Nunca interprete Escape como una eliminación confirmada.
Paso 4: Gestionar y restaurar el foco
Cuando se abre un modal, enfoque el mejor campo de entrada, botón de cancelar o encabezado; no coloque tabindex en el elemento dialog. Al cerrar, devuelva el foco al activador, o a un reemplazo estable si el activador fue eliminado.
Paso 5: Usar form method=dialog deliberadamente
method="dialog" cierra el diálogo y preserva el estado de los controles del formulario sin enviar una solicitud de red; el value del botón se convierte en returnValue. Si cancelar debe omitir la validación requerida, use formnovalidate o un close() explícito para que el usuario nunca quede atrapado.
Paso 6: Distinguir dialog de Popover
Un popover es no modal y reside en la capa superior (top layer). popover="auto" admite descarte ligero; manual permanece abierto hasta que se oculta explícitamente y permite múltiples popovers independientes. No utilice un popover donde se requiera la inercia modal.
Paso 7: Detectar soporte y proporcionar un fallback
Compruebe el soporte de HTMLDialogElement, showModal y closedby. Si no están disponibles, proporcione controles explícitos, manejo manual de Escape, gestión del foco y bloqueo del fondo. El fallback debe mantener el mismo contrato de cancelar y confirmar.
Paso 8: Probar el cierre y la accesibilidad
Pruebe Tab, Escape, clics exteriores, eventos táctiles, validaciones fallidas, aperturas repetidas, múltiples modales, gestos de retroceso y navegadores antiguos. Registre el motivo del cierre (confirmar, cancelar, escape, descarte ligero) y use un lector de pantalla para verificar el nombre accesible, el estado y el movimiento del foco.
Ejemplo de respuesta de alta calidad
“Una confirmación destructiva utiliza showModal() y closedby="closerequest"; el flujo más estricto utiliza none con un botón explícito de cancelar. La información de bajo riesgo puede usar any u popover="auto". method="dialog" devuelve el resultado, y cancelar puede omitir la validación cuando corresponda. Establezco el foco inicial, restauro el foco al activador, detecto soporte y aplico un fallback con controles explícitos y manejo manual de teclado/foco. Las pruebas cubren cada fuente de descarte y tecnología asistiva.”
Errores comunes
- Usar any para cada diálogo → las acciones destructivas se cierran accidentalmente → mapee closedby al riesgo.
- Agregar tabindex a dialog → la semántica de foco es incorrecta → enfoque un control interno o un encabezado.
- Tratar close como requestClose → se omite la lógica de confirmación → distinga entre cierre solicitado y directo.
- Hacer que el botón de cancelar de un formulario requerido falle la validación → el usuario queda atrapado → use formnovalidate o close.
- Reemplazar un modal con un popover → el fondo permanece interactivo → use showModal cuando la inercia sea importante.
- Probar únicamente con el mouse → los usuarios de teclado y pantallas táctiles no pueden salir → cubra Escape, Tab, clics exteriores y lectores de pantalla.
Preguntas de seguimiento y respuestas sólidas
Pregunta de seguimiento 1: ¿Cuál es la diferencia principal entre closerequest y none?
closerequest acepta Escape o una solicitud de cierre de la plataforma además de los controles del desarrollador; none solo acepta controles del desarrollador y se adapta a acciones irreversibles.
Pregunta de seguimiento 2: ¿Por qué showModal es más confiable que open?
Establece el estado modal, la inercia del fondo y el comportamiento de foco del navegador. Establecer únicamente open crea un diálogo no modal.
Pregunta de seguimiento 3: ¿Qué es returnValue después de Escape?
Escape no representa el valor de un botón de envío a menos que la aplicación establezca uno. Registre el motivo del cierre por separado como escape o solicitud de cierre (request-close).
Pregunta de seguimiento 4: ¿Cómo puede cancelar omitir la validación obligatoria?
Coloque formnovalidate en el control de cancelar o llame a close("cancel"); mantenga la validación normal en confirmar.
Pregunta de seguimiento 5: ¿Cuál es el fallback para navegadores antiguos?
Proporcione controles explícitos de abrir/cerrar y gestione manualmente Escape, el atrapamiento de foco (focus trap), el bloqueo de fondo y los motivos de cierre. Mantenga las pruebas de contrato idénticas cuando se restaure el soporte nativo.