kanban-app/frontend/src/context/modals/ModalRoot.tsx

47 lines
1.4 KiB
TypeScript

import { useEffect } from 'react';
import { createPortal } from 'react-dom';
import { useModal } from './useModal';
export const ModalRoot = () => {
const { isOpen, content, closeModal } = useModal();
// Handle Escape Key
useEffect(() => {
const handleKeyDown = (e: KeyboardEvent) => {
if (e.key === 'Escape' && isOpen) closeModal();
};
if (isOpen) window.addEventListener('keydown', handleKeyDown);
return () => window.removeEventListener('keydown', handleKeyDown);
}, [isOpen, closeModal]);
// Prevent body scroll when modal is open
useEffect(() => {
if (isOpen) {
document.body.style.overflow = 'hidden';
} else {
document.body.style.overflow = 'unset';
}
return () => { document.body.style.overflow = 'unset'; };
}, [isOpen]);
if (!isOpen || !content) return null;
return createPortal(
<div
className="fixed inset-0 z-50 flex items-center justify-center p-4 bg-black/50 backdrop-blur-sm"
onClick={closeModal} // Click outside to close
role="dialog"
aria-modal="true"
aria-labelledby="modal-title"
>
{/* Stop propagation so clicking modal content doesn't close it */}
<div
className="bg-white rounded-lg shadow-xl w-full max-w-md overflow-hidden flex flex-col transform transition-all"
onClick={(e) => e.stopPropagation()}
>
{content({ onClose: closeModal })}
</div>
</div>,
document.body
);
};