Spaces:
Running
Running
| import React from 'react'; | |
| import { X } from 'lucide-react'; | |
| export interface ModalProps { | |
| isOpen: boolean; | |
| onClose: () => void; | |
| title?: string; | |
| children: React.ReactNode; | |
| footerActions?: React.ReactNode; | |
| size?: 'sm' | 'md' | 'lg' | 'xl'; | |
| showCloseButton?: boolean; | |
| } | |
| export const Modal: React.FC<ModalProps> = ({ | |
| isOpen, | |
| onClose, | |
| title, | |
| children, | |
| footerActions, | |
| size = 'md', | |
| showCloseButton = false, | |
| }) => { | |
| if (!isOpen) return null; | |
| const sizeClasses = { | |
| sm: 'max-w-sm', | |
| md: 'max-w-md', | |
| lg: 'max-w-lg', | |
| xl: 'max-w-xl', | |
| }; | |
| return ( | |
| <div className="fixed inset-0 z-50 flex items-center justify-center bg-slate-900/60 backdrop-blur-xs animate-fade-in p-4"> | |
| {/* Backdrop click closer */} | |
| <div className="absolute inset-0" onClick={onClose} /> | |
| {/* Modal Container */} | |
| <div className={`bg-white rounded-2xl border border-slate-100 p-6 w-full ${sizeClasses[size]} shadow-xl space-y-4 animate-scale-up relative z-10`}> | |
| {showCloseButton && ( | |
| <button | |
| onClick={onClose} | |
| className="absolute top-4 right-4 text-slate-400 hover:text-slate-600 p-1 rounded-lg transition-colors cursor-pointer" | |
| type="button" | |
| > | |
| <X className="w-4.5 h-4.5" /> | |
| </button> | |
| )} | |
| <div className="space-y-2"> | |
| {title && <h3 className="text-base font-bold text-slate-900 text-center">{title}</h3>} | |
| <div className="text-sm text-slate-500 leading-relaxed"> | |
| {children} | |
| </div> | |
| </div> | |
| {footerActions && ( | |
| <div className="flex gap-2 pt-1"> | |
| {footerActions} | |
| </div> | |
| )} | |
| </div> | |
| </div> | |
| ); | |
| }; | |