atproto explorer pdsls.dev
atproto tool
at main 1.8 kB view raw
1import { ComponentProps, createEffect, onCleanup, Show } from "solid-js"; 2 3export interface ModalProps extends Pick<ComponentProps<"svg">, "children"> { 4 open?: boolean; 5 onClose?: () => void; 6 closeOnClick?: boolean; 7 nonBlocking?: boolean; 8} 9 10export const Modal = (props: ModalProps) => { 11 return ( 12 <Show when={props.open}> 13 <div 14 data-modal 15 class="fixed inset-0 z-50 h-full max-h-none w-full max-w-none bg-transparent text-neutral-900 dark:text-neutral-200" 16 classList={{ 17 "pointer-events-none": props.nonBlocking, 18 }} 19 ref={(node) => { 20 const handleEscape = (e: KeyboardEvent) => { 21 if (e.key === "Escape") { 22 const modals = document.querySelectorAll("[data-modal]"); 23 const lastModal = modals[modals.length - 1]; 24 if (lastModal === node) { 25 e.preventDefault(); 26 e.stopPropagation(); 27 if (props.onClose) props.onClose(); 28 } 29 } 30 }; 31 32 createEffect(() => { 33 if (!props.nonBlocking) document.body.style.overflow = "hidden"; 34 else document.body.style.overflow = "auto"; 35 }); 36 37 document.addEventListener("keydown", handleEscape); 38 39 onCleanup(() => { 40 document.body.style.overflow = "auto"; 41 document.removeEventListener("keydown", handleEscape); 42 }); 43 }} 44 onClick={(ev) => { 45 if ( 46 (props.closeOnClick ?? true) && 47 ev.target === ev.currentTarget && 48 !props.nonBlocking 49 ) { 50 if (props.onClose) props.onClose(); 51 } 52 }} 53 > 54 {props.children} 55 </div> 56 </Show> 57 ); 58};