Files
web/components/Lightbox/FullView.tsx
Niclas Edenvin dca02b90f0 Merged in fix/sw-1127-image-fixes (pull request #1123)
Fix/sw-1127 image fixes for lightbox

* fix(SW-1127): move back to top button behind lightbox

* fix(SW-1127): don't loop lightbox thumbnails

* fix(SW-1127): nicer animation in the gallery

This both fixes a bug in the gallery where the animation in the carousel
didn't work so good and also animates the images different directions
depending on if the user go left or right.


Approved-by: Matilda Landström
2025-01-07 07:56:17 +00:00

121 lines
3.2 KiB
TypeScript

"use client"
import { AnimatePresence, motion } from "framer-motion"
import { useState } from "react"
import ArrowRightIcon from "@/components/Icons/ArrowRight"
import CloseIcon from "@/components/Icons/Close"
import Image from "@/components/Image"
import Button from "@/components/TempDesignSystem/Button"
import Body from "@/components/TempDesignSystem/Text/Body"
import Caption from "@/components/TempDesignSystem/Text/Caption"
import styles from "./Lightbox.module.css"
import type { FullViewProps } from "@/types/components/lightbox/lightbox"
export default function FullView({
image,
onClose,
onNext,
onPrev,
currentIndex,
totalImages,
}: FullViewProps) {
const [animateLeft, setAnimateLeft] = useState(true)
function handleSwipe(offset: number) {
if (offset > 30) onPrev()
if (offset < -30) onNext()
}
function handleNext() {
setAnimateLeft(true)
onNext()
}
function handlePrev() {
setAnimateLeft(false)
onPrev()
}
const variants = {
initial: (animateLeft: boolean) => ({
opacity: 0,
x: animateLeft ? 300 : -300,
}),
animate: { opacity: 1, x: 0 },
exit: (animateLeft: boolean) => ({
opacity: 0,
x: animateLeft ? -300 : 300,
}),
}
return (
<div className={styles.fullViewContainer}>
<Button
intent="text"
size="small"
variant="icon"
className={styles.fullViewCloseButton}
onClick={onClose}
>
<CloseIcon
width={32}
height={32}
className={styles.fullViewCloseIcon}
color="white"
/>
</Button>
<div className={styles.fullViewHeader}>
<span className={styles.imagePosition}>
<Caption color="white">
{`${currentIndex + 1} / ${totalImages}`}
</Caption>
</span>
</div>
<div className={styles.fullViewImageContainer}>
<AnimatePresence initial={false} custom={animateLeft}>
<motion.div
key={image.imageSizes.medium}
custom={animateLeft}
variants={variants}
initial="initial"
animate="animate"
exit="exit"
transition={{ duration: 0.3 }}
className={styles.fullViewImage}
drag="x"
onDragEnd={(e, info) => handleSwipe(info.offset.x)}
>
<Image
alt={image.metaData.altText}
fill
src={image.imageSizes.medium}
style={{ objectFit: "cover" }}
/>
<div className={styles.fullViewFooter}>
{image.metaData.title && (
<Body color="white">{image.metaData.title}</Body>
)}
</div>
</motion.div>
</AnimatePresence>
</div>
<motion.button
className={`${styles.navigationButton} ${styles.fullViewPrevButton}`}
onClick={handlePrev}
>
<ArrowRightIcon color="burgundy" className={styles.leftTransformIcon} />
</motion.button>
<motion.button
className={`${styles.navigationButton} ${styles.fullViewNextButton}`}
onClick={handleNext}
>
<ArrowRightIcon color="burgundy" />
</motion.button>
</div>
)
}