Tengo un componente Modal , que usa el modal de Bulma CSS:
<script> import { createEventDispatcher } from 'svelte'; export let active; export let closeable = true; const dispatch = createEventDispatcher(); const closeModal = () => { active = false; dispatch("closeModal"); }; const closeModalSoft = () => { if (closeable) { closeModal(); } }; const closeModalKeyboard = (event) => { if (event.key === "Escape" && closeable) { closeModal(); } }; </script> <svelte:window on:keydown={closeModalKeyboard}/> <div class="modal is-clipped" class:is-active={active}> <div class="modal-background" on:click={closeModalSoft}/> <div class="modal-content"> <div class="container"> <slot /> </div> </div> {#if closeable} <button class="is-large modal-close" aria-label="close" on:click={closeModal}/> {/if} </div>Debe permitir el anidamiento arbitrario, por lo que puede, por ejemplo, tener un modal sobre un modal sobre el resto del sitio web.
Me gustaría permitir que los modales se cierren presionando el botón Cerrar, haciendo clic fuera del modal o usando la tecla Escape. Me gustaría que esto funcione como una pila: el modal superior se cierra primero. (Nota: si un modal no se closeable como se muestra en mi código, solo significa que el modal solo se puede cerrar mediante la manipulación active externamente).
Actualmente, el botón de cerrar y hacer clic fuera del modal funcionan con modales anidados. Sin embargo, escape siempre cerrará todos los modales, en lugar de solo el superior. Pero, dado el código, creo que esto es de esperar.
¿Qué necesitaría cambiar para que solo se cierre el modal superior ( closeable=true )?
He pensado en los siguientes enfoques, pero siento que debe haber mejores formas:
modal y is-active . Si es así, ignore la pulsación de tecla.:focus u otros modificadores en el elemento superior y luego un enfoque similar al anterior.Agregar el evento en la window es el enfoque incorrecto que conduce a este problema.
Los modales no deberían permitir que el enfoque lo deje, siendo ese el caso, debería poder manejar la presión Escape en el propio Modal. La forma más fácil de obtener la trampa de enfoque "gratis" sería usar un elemento de dialog nativo (aunque obtener soporte aún es relativamente reciente).
Una trampa de enfoque manual tendría que dirigir el enfoque al abrir/cerrar y al presionar cualquier Tab . Puede haber bibliotecas que ya implementen esto. En realidad, no recomendaría implementar tales componentes genéricos de todos modos y sugeriría el uso de una biblioteca de componentes en su lugar. Es fácil obtener accesibilidad y cosas como las interacciones del teclado muy mal.
Pautas para modales: https://www.w3.org/WAI/ARIA/apg/patterns/dialogmodal/