Merged in fix/SW-2831-image-gallery-history (pull request #2155)

fix(SW-2831): checking isOpen before rendering Lightbox component to avoid spamming the window history

* fix(SW-2831): checking isOpen before rendering Lightbox component to avoid spamming the window history


Approved-by: Linus Flood
This commit is contained in:
Erik Tiekstra
2025-05-20 07:38:13 +00:00
committed by Linus Flood
parent f4ef5a342f
commit f60d07fd9e
5 changed files with 71 additions and 76 deletions

View File

@@ -69,18 +69,19 @@ export default function TopImages({ images, destinationName }: TopImageProps) {
defaultMessage: "See all photos", defaultMessage: "See all photos",
})} })}
</Button> </Button>
<Lightbox {lightboxState.open ? (
images={lightboxImages} <Lightbox
dialogTitle={intl.formatMessage( images={lightboxImages}
{ dialogTitle={intl.formatMessage(
defaultMessage: "{title} - Image gallery", {
}, defaultMessage: "{title} - Image gallery",
{ title: destinationName } },
)} { title: destinationName }
isOpen={lightboxState.open} )}
activeIndex={lightboxState.activeIndex} activeIndex={lightboxState.activeIndex}
onClose={() => setLightboxState({ open: false, activeIndex: 0 })} onClose={() => setLightboxState({ open: false, activeIndex: 0 })}
/> />
) : null}
</> </>
)} )}
</div> </div>

View File

@@ -71,18 +71,21 @@ export default function PreviewImages({
defaultMessage: "See all photos", defaultMessage: "See all photos",
})} })}
</Button> </Button>
<Lightbox {lightboxState.isOpen ? (
images={lightboxImages} <Lightbox
dialogTitle={intl.formatMessage( images={lightboxImages}
{ dialogTitle={intl.formatMessage(
defaultMessage: "{title} - Image gallery", {
}, defaultMessage: "{title} - Image gallery",
{ title: hotelName } },
)} { title: hotelName }
isOpen={lightboxState.isOpen} )}
activeIndex={lightboxState.activeIndex} activeIndex={lightboxState.activeIndex}
onClose={() => setLightboxState({ activeIndex: 0, isOpen: false })} onClose={() =>
/> setLightboxState({ activeIndex: 0, isOpen: false })
}
/>
) : null}
</> </>
)} )}
</div> </div>

View File

@@ -58,13 +58,14 @@ function ImageGallery({
})} })}
/> />
</div> </div>
<Lightbox {isOpen ? (
images={images} <Lightbox
dialogTitle={title} images={images}
isOpen={isOpen} dialogTitle={title}
onClose={() => setIsOpen(false)} onClose={() => setIsOpen(false)}
hideLabel={hideLabel} hideLabel={hideLabel}
/> />
) : null}
</> </>
) )
} }

View File

@@ -14,19 +14,12 @@ export default function Lightbox({
images, images,
dialogTitle, dialogTitle,
onClose, onClose,
isOpen,
activeIndex = 0, activeIndex = 0,
hideLabel, hideLabel,
}: LightboxProps) { }: LightboxProps) {
const [selectedImageIndex, setSelectedImageIndex] = useState(activeIndex) const [selectedImageIndex, setSelectedImageIndex] = useState(activeIndex)
const [isFullView, setIsFullView] = useState(false) const [isFullView, setIsFullView] = useState(false)
useEffect(() => {
if (isOpen) {
setIsFullView(false)
}
}, [isOpen])
useEffect(() => { useEffect(() => {
setSelectedImageIndex(activeIndex) setSelectedImageIndex(activeIndex)
}, [activeIndex]) }, [activeIndex])
@@ -62,7 +55,7 @@ export default function Lightbox({
return ( return (
<ModalOverlay <ModalOverlay
isOpen={isOpen} isOpen={true}
onOpenChange={handleClose} onOpenChange={handleClose}
className={styles.overlay} className={styles.overlay}
isDismissable isDismissable
@@ -70,42 +63,40 @@ export default function Lightbox({
<Modal> <Modal>
<AnimatePresence> <AnimatePresence>
<Dialog aria-label={dialogTitle}> <Dialog aria-label={dialogTitle}>
{isOpen && ( <motion.div
<motion.div className={`${styles.content} ${
className={`${styles.content} ${ isFullView ? styles.fullViewContent : styles.galleryContent
isFullView ? styles.fullViewContent : styles.galleryContent }`}
}`} initial={{ opacity: 0, scale: 0.95 }}
initial={{ opacity: 0, scale: 0.95 }} animate={{ opacity: 1, scale: 1, x: "-50%", y: "-50%" }}
animate={{ opacity: 1, scale: 1, x: "-50%", y: "-50%" }} exit={{ opacity: 0, scale: 0.95 }}
exit={{ opacity: 0, scale: 0.95 }} transition={{ duration: 0.2 }}
transition={{ duration: 0.2 }} >
> {isFullView ? (
{isFullView ? ( <FullView
<FullView image={images[selectedImageIndex]}
image={images[selectedImageIndex]} onClose={() => setIsFullView(false)}
onClose={() => setIsFullView(false)} onNext={handleNext}
onNext={handleNext} onPrev={handlePrev}
onPrev={handlePrev} currentIndex={selectedImageIndex}
currentIndex={selectedImageIndex} totalImages={images.length}
totalImages={images.length} hideLabel={hideLabel}
hideLabel={hideLabel} />
/> ) : (
) : ( <Gallery
<Gallery images={images}
images={images} onClose={handleClose}
onClose={handleClose} onSelectImage={(image) => {
onSelectImage={(image) => { setSelectedImageIndex(
setSelectedImageIndex( images.findIndex((img) => img === image)
images.findIndex((img) => img === image) )
) }}
}} onImageClick={() => setIsFullView(true)}
onImageClick={() => setIsFullView(true)} selectedImage={images[selectedImageIndex]}
selectedImage={images[selectedImageIndex]} hideLabel={hideLabel}
hideLabel={hideLabel} />
/> )}
)} </motion.div>
</motion.div>
)}
</Dialog> </Dialog>
</AnimatePresence> </AnimatePresence>
</Modal> </Modal>

View File

@@ -4,7 +4,6 @@ export interface LightboxProps {
images: GalleryImage[] images: GalleryImage[]
dialogTitle: string /* Accessible title for dialog screen readers */ dialogTitle: string /* Accessible title for dialog screen readers */
onClose: () => void onClose: () => void
isOpen: boolean
activeIndex?: number activeIndex?: number
hideLabel?: boolean hideLabel?: boolean
} }