File size: 1,796 Bytes
25732fb | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 | import React from 'react'
import { motion, AnimatePresence } from 'framer-motion'
import { X } from 'lucide-react'
const Modal = ({ isOpen, onClose, title, children, size = 'md' }) => {
const sizes = {
sm: 'max-w-md',
md: 'max-w-2xl',
lg: 'max-w-4xl',
xl: 'max-w-6xl'
}
return (
<AnimatePresence>
{isOpen && (
<>
{/* Backdrop */}
<motion.div
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
exit={{ opacity: 0 }}
onClick={onClose}
className="fixed inset-0 bg-black/50 backdrop-blur-sm z-50"
/>
{/* Modal */}
<div className="fixed inset-0 flex items-center justify-center z-50 p-4">
<motion.div
initial={{ opacity: 0, scale: 0.9, y: 20 }}
animate={{ opacity: 1, scale: 1, y: 0 }}
exit={{ opacity: 0, scale: 0.9, y: 20 }}
className={`w-full ${sizes[size]} glass-effect rounded-2xl shadow-2xl max-h-[90vh] overflow-hidden`}
>
{/* Header */}
<div className="flex items-center justify-between p-6 border-b border-slate-200">
<h2 className="text-2xl font-bold text-slate-800">{title}</h2>
<button
onClick={onClose}
className="p-2 rounded-xl hover:bg-slate-100 transition-colors"
>
<X className="w-6 h-6 text-slate-600" />
</button>
</div>
{/* Content */}
<div className="p-6 overflow-y-auto max-h-[calc(90vh-5rem)]">
{children}
</div>
</motion.div>
</div>
</>
)}
</AnimatePresence>
)
}
export default Modal |