Files
clube67_newwhats.local/clube67/newwhats.local/frontend/components/ui/Modal.tsx
T
VPS 4 Deploy Agent 2f8c04a0a7
continuous-integration/webhook Falha no deploy de clube67_newwhats.local (VPS 4)
chore(ops): restore all source files in newwhats.clube67.com
2026-05-18 03:28:29 +02:00

78 lines
2.3 KiB
TypeScript

import React from 'react';
import { motion, AnimatePresence } from 'framer-motion';
import { X } from 'lucide-react';
interface ModalProps {
open: boolean;
onClose: () => void;
title?: string;
icon?: React.ReactNode;
size?: 'sm' | 'md' | 'lg';
children: React.ReactNode;
footer?: React.ReactNode;
}
const sizeClasses = {
sm: 'max-w-md',
md: 'max-w-lg',
lg: 'max-w-2xl',
};
export default function Modal({ open, onClose, title, icon, size = 'md', children, footer }: ModalProps) {
return (
<AnimatePresence>
{open && (
<div className="fixed inset-0 z-50 flex items-center justify-center p-4">
{/* Backdrop */}
<motion.div
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
exit={{ opacity: 0 }}
className="absolute inset-0 bg-black/60 backdrop-blur-sm"
onClick={onClose}
/>
{/* Container */}
<motion.div
initial={{ opacity: 0, scale: 0.95, y: 10 }}
animate={{ opacity: 1, scale: 1, y: 0 }}
exit={{ opacity: 0, scale: 0.95, y: 10 }}
transition={{ duration: 0.2, ease: 'easeOut' }}
className={`relative w-full ${sizeClasses[size]} glass-elevated rounded-3xl shadow-premium shimmer-line`}
>
{/* Header */}
{title && (
<div className="flex items-center gap-3 p-6 pb-0">
{icon && (
<div className="w-10 h-10 rounded-xl bg-brand-500/15 flex items-center justify-center text-brand-400">
{icon}
</div>
)}
<h2 className="text-lg font-bold text-white">{title}</h2>
</div>
)}
{/* Close */}
<button
onClick={onClose}
className="absolute top-4 right-4 p-2 text-slate-400 hover:text-white hover:bg-white/5 rounded-lg transition-colors"
>
<X size={18} />
</button>
{/* Body */}
<div className="p-6">{children}</div>
{/* Footer */}
{footer && (
<div className="border-t border-white/5 px-6 py-4 flex justify-end gap-3">
{footer}
</div>
)}
</motion.div>
</div>
)}
</AnimatePresence>
);
}