react
This commit is contained in:
49
frontend/src/components/Modal.jsx
Normal file
49
frontend/src/components/Modal.jsx
Normal file
@@ -0,0 +1,49 @@
|
||||
import React, { useEffect } from 'react';
|
||||
import { FiX } from 'react-icons/fi';
|
||||
|
||||
const Modal = ({ open, onClose, title, subtitle, children, size = 'md' }) => {
|
||||
useEffect(() => {
|
||||
if (!open) return;
|
||||
const handler = (e) => { if (e.key === 'Escape') onClose(); };
|
||||
window.addEventListener('keydown', handler);
|
||||
document.body.style.overflow = 'hidden';
|
||||
return () => {
|
||||
window.removeEventListener('keydown', handler);
|
||||
document.body.style.overflow = '';
|
||||
};
|
||||
}, [open, onClose]);
|
||||
|
||||
if (!open) return null;
|
||||
|
||||
const widths = {
|
||||
sm: 'max-w-md',
|
||||
md: 'max-w-2xl',
|
||||
lg: 'max-w-4xl',
|
||||
};
|
||||
|
||||
return (
|
||||
<div
|
||||
className="fixed inset-0 z-30 bg-gray-900/40 backdrop-blur-sm flex items-start justify-center p-4 sm:p-8 overflow-y-auto"
|
||||
onClick={(e) => { if (e.target === e.currentTarget) onClose(); }}
|
||||
>
|
||||
<div className={`bg-white rounded-xl shadow-xl border border-gray-200 w-full ${widths[size]} my-8`}>
|
||||
<div className="flex items-start justify-between px-6 py-4 border-b border-gray-100">
|
||||
<div>
|
||||
<h2 className="text-lg font-semibold text-gray-900">{title}</h2>
|
||||
{subtitle && <p className="text-sm text-gray-500 mt-0.5">{subtitle}</p>}
|
||||
</div>
|
||||
<button
|
||||
onClick={onClose}
|
||||
className="text-gray-400 hover:text-gray-700 p-1 rounded-lg hover:bg-gray-100 transition-colors"
|
||||
aria-label="Close"
|
||||
>
|
||||
<FiX className="w-5 h-5" />
|
||||
</button>
|
||||
</div>
|
||||
<div className="p-6">{children}</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default Modal;
|
||||
Reference in New Issue
Block a user