Files
web/apps/scandic-web/components/Lightbox/index.tsx
Erik Tiekstra 8b32abbefc Fix/SW-1563 accessibility
* fix(SW-1563): Added new IconButton component to the design system and removed Icon variant inside the Button component
* fix(SW-1563): Added buttons around clickable images and changed to design system components
* fix(SW-1563): Renamed variants to match Figma
* fix(SW-1563): Renamed AriaButton to ButtonRAC

Approved-by: Michael Zetterberg
Approved-by: Matilda Landström
2025-05-02 06:27:30 +00:00

101 lines
2.8 KiB
TypeScript

"use client"
import { AnimatePresence, motion } from "framer-motion"
import { useEffect, useState } from "react"
import { Dialog, Modal, ModalOverlay } from "react-aria-components"
import FullView from "./FullView"
import Gallery from "./Gallery"
import styles from "./lightbox.module.css"
import type { LightboxProps } from "@/types/components/lightbox/lightbox"
export default function Lightbox({
images,
dialogTitle,
onClose,
isOpen,
activeIndex = 0,
hideLabel,
}: LightboxProps) {
const [selectedImageIndex, setSelectedImageIndex] = useState(activeIndex)
const [isFullView, setIsFullView] = useState(false)
useEffect(() => {
if (isOpen) {
setIsFullView(false)
}
}, [isOpen])
useEffect(() => {
setSelectedImageIndex(activeIndex)
}, [activeIndex])
function handleClose() {
setSelectedImageIndex(0)
onClose()
}
function handleNext() {
setSelectedImageIndex((prevIndex) => (prevIndex + 1) % images.length)
}
function handlePrev() {
setSelectedImageIndex(
(prevIndex) => (prevIndex - 1 + images.length) % images.length
)
}
return (
<ModalOverlay
isOpen={isOpen}
onOpenChange={handleClose}
className={styles.overlay}
isDismissable
>
<Modal>
<AnimatePresence>
<Dialog aria-label={dialogTitle}>
{isOpen && (
<motion.div
className={`${styles.content} ${
isFullView ? styles.fullViewContent : styles.galleryContent
}`}
initial={{ opacity: 0, scale: 0.95 }}
animate={{ opacity: 1, scale: 1, x: "-50%", y: "-50%" }}
exit={{ opacity: 0, scale: 0.95 }}
transition={{ duration: 0.2 }}
>
{isFullView ? (
<FullView
image={images[selectedImageIndex]}
onClose={() => setIsFullView(false)}
onNext={handleNext}
onPrev={handlePrev}
currentIndex={selectedImageIndex}
totalImages={images.length}
hideLabel={hideLabel}
/>
) : (
<Gallery
images={images}
onClose={onClose}
onSelectImage={(image) => {
setSelectedImageIndex(
images.findIndex((img) => img === image)
)
}}
onImageClick={() => setIsFullView(true)}
selectedImage={images[selectedImageIndex]}
hideLabel={hideLabel}
/>
)}
</motion.div>
)}
</Dialog>
</AnimatePresence>
</Modal>
</ModalOverlay>
)
}