NitinBot002's picture
Initial commit with all project files
f4854a1
import { useEffect } from 'react';
import { motion, AnimatePresence } from 'framer-motion';
import { HiX } from 'react-icons/hi';
import './Modal.css';
/**
* Modal component with overlay, animation, and close behavior
*/
export default function Modal({ isOpen, onClose, title, children, size = 'md', showClose = true }) {
// Prevent body scroll when modal is open
useEffect(() => {
if (isOpen) {
document.body.style.overflow = 'hidden';
} else {
document.body.style.overflow = '';
}
return () => { document.body.style.overflow = ''; };
}, [isOpen]);
// Close on Escape
useEffect(() => {
const handleEsc = (e) => e.key === 'Escape' && onClose();
if (isOpen) window.addEventListener('keydown', handleEsc);
return () => window.removeEventListener('keydown', handleEsc);
}, [isOpen, onClose]);
return (
<AnimatePresence>
{isOpen && (
<div className="modal-overlay" onClick={onClose}>
<motion.div
className={`modal modal--${size}`}
initial={{ opacity: 0, scale: 0.9, y: 20 }}
animate={{ opacity: 1, scale: 1, y: 0 }}
exit={{ opacity: 0, scale: 0.9, y: 20 }}
transition={{ type: 'spring', damping: 25, stiffness: 300 }}
onClick={(e) => e.stopPropagation()}
>
{(title || showClose) && (
<div className="modal__header">
{title && <h3 className="modal__title">{title}</h3>}
{showClose && (
<button className="modal__close" onClick={onClose} aria-label="Close modal">
<HiX size={20} />
</button>
)}
</div>
)}
<div className="modal__body">
{children}
</div>
</motion.div>
</div>
)}
</AnimatePresence>
);
}