70 lines
1.7 KiB
TypeScript
70 lines
1.7 KiB
TypeScript
"use client"
|
|
|
|
import { useEffect } from "react"
|
|
import Image from "next/image"
|
|
import { X } from "lucide-react"
|
|
|
|
interface ImageLightboxProps {
|
|
src: string
|
|
alt: string
|
|
isOpen: boolean
|
|
onClose: () => void
|
|
}
|
|
|
|
export default function ImageLightbox({ src, alt, isOpen, onClose }: ImageLightboxProps) {
|
|
useEffect(() => {
|
|
if (isOpen) {
|
|
document.body.style.overflow = "hidden"
|
|
} else {
|
|
document.body.style.overflow = "unset"
|
|
}
|
|
|
|
return () => {
|
|
document.body.style.overflow = "unset"
|
|
}
|
|
}, [isOpen])
|
|
|
|
useEffect(() => {
|
|
const handleEscape = (e: KeyboardEvent) => {
|
|
if (e.key === "Escape") {
|
|
onClose()
|
|
}
|
|
}
|
|
|
|
if (isOpen) {
|
|
document.addEventListener("keydown", handleEscape)
|
|
}
|
|
|
|
return () => {
|
|
document.removeEventListener("keydown", handleEscape)
|
|
}
|
|
}, [isOpen, onClose])
|
|
|
|
if (!isOpen) return null
|
|
|
|
return (
|
|
<div className="fixed inset-0 z-50 bg-black bg-opacity-90 flex items-center justify-center p-4" onClick={onClose}>
|
|
<div className="relative max-w-7xl max-h-full">
|
|
<button
|
|
onClick={onClose}
|
|
className="absolute top-4 right-4 z-10 bg-white bg-opacity-20 hover:bg-opacity-30 rounded-full p-2 transition-colors"
|
|
aria-label="Close image"
|
|
>
|
|
<X className="w-6 h-6 text-white" />
|
|
</button>
|
|
|
|
<div className="relative" onClick={(e) => e.stopPropagation()}>
|
|
<Image
|
|
src={src || "/placeholder.svg"}
|
|
alt={alt}
|
|
width={1200}
|
|
height={1200}
|
|
className="max-w-full max-h-[90vh] object-contain rounded-lg"
|
|
priority
|
|
/>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
)
|
|
}
|