11'use client' ;
22
3- import { useState } from 'react' ;
3+ import { useEffect , useState } from 'react' ;
4+ import { createPortal } from 'react-dom' ;
45import Image from 'next/image' ;
56import { X } from 'lucide-react' ;
67
@@ -15,6 +16,23 @@ interface LightboxImageProps {
1516export function LightboxImage ( { src, alt, width, height, className } : LightboxImageProps ) {
1617 const [ isOpen , setIsOpen ] = useState ( false ) ;
1718
19+ useEffect ( ( ) => {
20+ if ( ! isOpen ) return ;
21+
22+ const previousOverflow = document . body . style . overflow ;
23+ const closeOnEscape = ( event : KeyboardEvent ) => {
24+ if ( event . key === 'Escape' ) setIsOpen ( false ) ;
25+ } ;
26+
27+ document . body . style . overflow = 'hidden' ;
28+ document . addEventListener ( 'keydown' , closeOnEscape ) ;
29+
30+ return ( ) => {
31+ document . body . style . overflow = previousOverflow ;
32+ document . removeEventListener ( 'keydown' , closeOnEscape ) ;
33+ } ;
34+ } , [ isOpen ] ) ;
35+
1836 return (
1937 < >
2038 { /* Thumbnail */ }
@@ -31,11 +49,14 @@ export function LightboxImage({ src, alt, width, height, className }: LightboxIm
3149 />
3250 </ div >
3351
34- { /* Lightbox Modal */ }
35- { isOpen && (
52+ { /* Render outside animated/overflow-hidden thumbnail cards so fixed positioning is viewport-relative. */ }
53+ { isOpen && createPortal (
3654 < div
37- className = "fixed inset-0 z-50 flex items-center justify-center bg-black/90 p-4"
55+ className = "fixed inset-0 z-[100] flex items-center justify-center bg-black/90 p-4"
3856 onClick = { ( ) => setIsOpen ( false ) }
57+ role = "dialog"
58+ aria-modal = "true"
59+ aria-label = { `${ alt } preview` }
3960 >
4061 < button
4162 className = "absolute top-4 right-4 p-2 text-white hover:bg-white/10 rounded-lg transition-colors"
@@ -54,7 +75,8 @@ export function LightboxImage({ src, alt, width, height, className }: LightboxIm
5475 onClick = { ( e ) => e . stopPropagation ( ) }
5576 />
5677 </ div >
57- </ div >
78+ </ div > ,
79+ document . body ,
5880 ) }
5981 </ >
6082 ) ;
0 commit comments