From 5222d1ab22fbc70af62010e79acbe2455f90745a Mon Sep 17 00:00:00 2001 From: trafficlunar Date: Wed, 4 Feb 2026 21:37:51 +0000 Subject: [PATCH] feat: redesign image viewer --- src/components/image-viewer.tsx | 121 +++++++++++++++----------------- 1 file changed, 56 insertions(+), 65 deletions(-) diff --git a/src/components/image-viewer.tsx b/src/components/image-viewer.tsx index dfa62cc..eb8ec28 100644 --- a/src/components/image-viewer.tsx +++ b/src/components/image-viewer.tsx @@ -20,7 +20,7 @@ export default function ImageViewer({ src, alt, width, height, className, images const [isOpen, setIsOpen] = useState(false); const [isVisible, setIsVisible] = useState(false); - const [emblaRef, emblaApi] = useEmblaCarousel(); + const [emblaRef, emblaApi] = useEmblaCarousel({ loop: true, duration: 15 }); const [selectedIndex, setSelectedIndex] = useState(0); const [scrollSnaps, setScrollSnaps] = useState([]); @@ -44,7 +44,7 @@ export default function ImageViewer({ src, alt, width, height, className, images // Keep order of images whilst opening at src prop const index = images.indexOf(src); if (index !== -1) { - emblaApi.scrollTo(index); + emblaApi.scrollTo(index, true); setSelectedIndex(index); } @@ -80,83 +80,74 @@ export default function ImageViewer({ src, alt, width, height, className, images
-
-
- -
+ + -
-
- {imagesMap.map((image, index) => ( -
- {alt} -
- ))} -
+
+
+ {imagesMap.map((image, index) => ( +
+ {alt} +
+ ))}
- {images.length != 0 && ( + {images.length > 1 && ( <> + {/* Carousel counter */} +
+ {selectedIndex + 1} / {images.length} +
+ {/* Carousel buttons */} {/* Prev button */} -
emblaApi?.scrollPrev()} + className={`absolute left-2 top-1/2 -translate-y-1/2 pill button p-0.5! aspect-square text-4xl transition-opacity duration-300 ${isVisible ? "opacity-100" : "opacity-0"}`} > - -
+ + {/* Next button */} -
emblaApi?.scrollNext()} + className={`absolute right-2 top-1/2 -translate-y-1/2 pill button p-0.5! aspect-square text-4xl transition-opacity duration-300 ${isVisible ? "opacity-100" : "opacity-0"}`} > - -
+ + {/* Carousel snaps */}
@@ -165,14 +156,14 @@ export default function ImageViewer({ src, alt, width, height, className, images key={index} aria-label={`Go to ${index} in Carousel`} onClick={() => emblaApi?.scrollTo(index)} - className={`size-2.5 cursor-pointer rounded-full ${index === selectedIndex ? "bg-black" : "bg-black/25"}`} + className={`size-2 cursor-pointer rounded-full transition-all duration-300 ${index === selectedIndex ? "bg-orange-300 w-8" : "bg-orange-300/40"}`} /> ))}
)}
, - document.body + document.body, )} );