Files
lct2025-lonolith/Frontend/components/ui/modal.jsx
Nikolai Papin 90abe15a8f feat: compose;
feat: frontend added
2025-10-02 22:17:38 +03:00

63 lines
2.0 KiB
JavaScript

'use client';
import { motion, AnimatePresence } from 'framer-motion';
import { X } from 'lucide-react';
import { useEffect } from 'react';
export default function Modal({ isOpen, onClose, children, title, size = 'md' }) {
useEffect(() => {
if (isOpen) {
document.body.style.overflow = 'hidden';
} else {
document.body.style.overflow = 'unset';
}
return () => {
document.body.style.overflow = 'unset';
};
}, [isOpen]);
const sizeClasses = {
sm: 'max-w-md',
md: 'max-w-2xl',
lg: 'max-w-4xl',
xl: 'max-w-6xl',
};
return (
<AnimatePresence>
{isOpen && (
<>
<motion.div
className="fixed inset-0 bg-black/80 backdrop-blur-sm z-50"
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
exit={{ opacity: 0 }}
onClick={onClose}
/>
<div className="fixed inset-0 z-50 flex items-center justify-center p-4 overflow-y-auto">
<motion.div
className={`relative w-full ${sizeClasses[size]} bg-gradient-to-br from-slate-900 to-slate-800 rounded-xl border border-slate-700 shadow-2xl`}
initial={{ opacity: 0, scale: 0.95, y: 20 }}
animate={{ opacity: 1, scale: 1, y: 0 }}
exit={{ opacity: 0, scale: 0.95, y: 20 }}
transition={{ duration: 0.2 }}
>
{title && (
<div className="flex items-center justify-between p-6 border-b border-slate-700">
<h2 className="text-2xl font-bold text-white">{title}</h2>
<button
onClick={onClose}
className="p-2 hover:bg-slate-700 rounded-lg transition-colors"
>
<X className="w-5 h-5 text-slate-400" />
</button>
</div>
)}
<div className="p-6">{children}</div>
</motion.div>
</div>
</>
)}
</AnimatePresence>
);
}