This commit is contained in:
Vula Builder
2026-07-26 17:04:59 +00:00
parent 0ec6b9768d
commit 7f389e1316
+59
View File
@@ -0,0 +1,59 @@
'use client'
import { useEffect } from "react"
import { X } from 'lucide-react'
import { cn } from "@/lib/utils"
interface ModalProps {
isOpen: boolean
onClose: () => void
title?: string
children: React.ReactNode
className?: string
}
export default function Modal({ isOpen, onClose, title, children, className }: ModalProps) {
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 = ""
}
}, [isOpen, onClose])
if (!isOpen) return null
return (
<div className="fixed inset-0 z-50 flex items-center justify-center">
<div
className="fixed inset-0 bg-background/80 backdrop-blur-sm"
onClick={onClose}
aria-hidden="true"
/>
<div
className={cn(
"relative z-50 w-full max-w-lg rounded-lg border border-border bg-card p-6 shadow-lg",
className
)}
>
<div className="flex items-center justify-between mb-4">
{title && <h2 className="text-xl font-semibold text-foreground">{title}</h2>}
<button
onClick={onClose}
className="ml-auto rounded-md p-1 text-muted-foreground hover:bg-accent hover:text-accent-foreground focus:outline-none focus:bg-accent"
aria-label="Close modal"
>
<X size={20} />
</button>
</div>
{children}
</div>
</div>
)
}