"use client"; import { useEffect, useRef } from "react"; import { motion, AnimatePresence } from "motion/react"; interface ModalProps { open: boolean; onClose: () => void; children: React.ReactNode; title?: string; className?: string; } export function Modal({ open, onClose, children, title, className = "" }: ModalProps) { const modalRef = useRef(null); const previousFocusRef = useRef(null); // Lock body scroll when modal is open useEffect(() => { if (open) { document.body.style.overflow = "hidden"; // Store current focus previousFocusRef.current = document.activeElement as HTMLElement; } else { document.body.style.overflow = ""; // Restore focus when modal closes if (previousFocusRef.current) { previousFocusRef.current.focus(); } } return () => { document.body.style.overflow = ""; }; }, [open]); // Focus trap and ESC key handling useEffect(() => { if (!open || !modalRef.current) return; const handleKeyDown = (event: KeyboardEvent) => { if (event.key === "Escape") { onClose(); return; } if (event.key === "Tab") { const modal = modalRef.current; if (!modal) return; const focusableElements = modal.querySelectorAll( 'button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])' ); const firstElement = focusableElements[0] as HTMLElement; const lastElement = focusableElements[focusableElements.length - 1] as HTMLElement; if (event.shiftKey) { if (document.activeElement === firstElement) { event.preventDefault(); lastElement?.focus(); } } else { if (document.activeElement === lastElement) { event.preventDefault(); firstElement?.focus(); } } } }; document.addEventListener("keydown", handleKeyDown); return () => document.removeEventListener("keydown", handleKeyDown); }, [open, onClose]); return ( {open && ( e.stopPropagation()} > {title && (

{title}

)}
{children}
)}
); }