This commit is contained in:
Vula Builder
2026-07-25 13:58:37 +00:00
parent 5277e3dadb
commit 2af01442a3
+67
View File
@@ -0,0 +1,67 @@
'use client'
import { cn } from "@/lib/utils"
import React, { useEffect, useRef } from 'react'
import { X } from 'lucide-react'
interface ModalProps {
isOpen: boolean
onClose: () => void
title?: string
children: React.ReactNode
className?: string
}
export default function Modal({ isOpen, onClose, title, children, className }: ModalProps) {
const overlayRef = useRef<HTMLDivElement>(null)
useEffect(() => {
const handleEscape = (e: KeyboardEvent) => {
if (e.key === 'Escape') onClose()
}
if (isOpen) {
document.addEventListener('keydown', handleEscape)
document.body.style.overflow = 'hidden'
}
return () => {
document.removeEventListener('keydown', handleEscape)
document.body.style.overflow = 'unset'
}
}, [isOpen, onClose])
if (!isOpen) return null
return (
<div
ref={overlayRef}
className="fixed inset-0 z-50 flex items-center justify-center bg-[#210d0d]/60 backdrop-blur-sm"
onClick={(e) => {
if (e.target === overlayRef.current) onClose()
}}
>
<div
className={cn(
"relative w-full max-w-lg mx-4 bg-[#f9f4f4] rounded-lg shadow-xl border border-[#e2d4d4] overflow-hidden",
className
)}
role="dialog"
aria-modal="true"
aria-label={title}
>
<div className="flex items-center justify-between p-4 border-b border-[#e2d4d4]">
{title && <h2 className="text-lg font-semibold text-[#210d0d]">{title}</h2>}
<button
onClick={onClose}
className="p-1 rounded-md text-[#210d0d]/70 hover:text-[#210d0d] hover:bg-[#dc2626]/10 focus:outline-none focus:border-[#dc2626]"
aria-label="Close modal"
>
<X className="w-5 h-5" />
</button>
</div>
<div className="p-4">
{children}
</div>
</div>
</div>
)
}