'use client'; import React, { useEffect, useRef } from 'react'; import { clsx } from 'clsx'; import { twMerge } from 'tailwind-merge'; export interface ModalProps { open: boolean; onClose: () => void; title?: string; children: React.ReactNode; footer?: React.ReactNode; className?: string; } export const Modal: React.FC = ({ open, onClose, title, children, footer, className, }) => { const overlayRef = useRef(null); // Close on Escape useEffect(() => { if (!open) return; const handler = (e: KeyboardEvent) => { if (e.key === 'Escape') onClose(); }; document.addEventListener('keydown', handler); return () => document.removeEventListener('keydown', handler); }, [open, onClose]); // Lock body scroll useEffect(() => { if (open) { document.body.style.overflow = 'hidden'; return () => { document.body.style.overflow = ''; }; } }, [open]); if (!open) return null; return (
{ if (e.target === overlayRef.current) onClose(); }} > {/* Backdrop */}
{/* Panel */}
{/* Header */} {title && (

{title}

)} {/* Body */}
{children}
{/* Footer */} {footer && (
{footer}
)}
); }; Modal.displayName = 'Modal';