Browse Source

🛠️ Fixed a bug in GallerySlider component

🚧 Work in progress on GallerySlider
📸 Added new images to the gallery
 Implemented swipe functionality
🎨 Improved styling in GallerySlider component
main
John Doe 1 year ago
parent
commit
1a2139b6fc
  1. 146
      src/components/GallerySlider.tsx

146
src/components/GallerySlider.tsx

@ -0,0 +1,146 @@
"use client";
import { ChevronLeftIcon, ChevronRightIcon } from "@heroicons/react/24/outline";
import { AnimatePresence, motion, MotionConfig } from "framer-motion";
import Image, { StaticImageData } from "next/image";
import { useState } from "react";
import { useSwipeable } from "react-swipeable";
import { variants } from "@/utils/animationVariants";
import Link from "next/link";
import { Route } from "@/routers/types";
export interface GallerySliderProps {
className?: string;
galleryImgs: (StaticImageData | string)[];
ratioClass?: string;
uniqueID: string;
href?: Route<string>;
imageClass?: string;
galleryClass?: string;
navigation?: boolean;
}
export default function GallerySlider({
className = "",
galleryImgs,
ratioClass = "aspect-w-4 aspect-h-3",
imageClass = "",
uniqueID = "uniqueID",
galleryClass = "rounded-xl",
href = "/listing-stay-detail",
navigation = true,
}: GallerySliderProps) {
const [loaded, setLoaded] = useState(false);
const [index, setIndex] = useState(0);
const [direction, setDirection] = useState(0);
const images = galleryImgs;
function changePhotoId(newVal: number) {
if (newVal > index) {
setDirection(1);
} else {
setDirection(-1);
}
setIndex(newVal);
}
const handlers = useSwipeable({
onSwipedLeft: () => {
if (index < images?.length - 1) {
changePhotoId(index + 1);
}
},
onSwipedRight: () => {
if (index > 0) {
changePhotoId(index - 1);
}
},
trackMouse: true,
});
let currentImage = images[index];
return (
<MotionConfig
transition={{
x: { type: "spring", stiffness: 300, damping: 30 },
opacity: { duration: 0.2 },
}}
>
<div
className={`relative group group/cardGallerySlider ${className}`}
{...handlers}
>
{/* Main image */}
<div className={`w-full overflow-hidden ${galleryClass}`}>
<Link
href={href}
className={`relative flex items-center justify-center ${ratioClass}`}
>
<AnimatePresence initial={false} custom={direction}>
<motion.div
key={index}
custom={direction}
variants={variants(340, 1)}
initial="enter"
animate="center"
exit="exit"
className="absolute inset-0"
>
<Image
src={currentImage || ""}
fill
alt="listing card gallery"
className={`object-cover ${imageClass}`}
onLoadingComplete={() => setLoaded(true)}
sizes="(max-width: 1025px) 100vw, 300px"
/>
</motion.div>
</AnimatePresence>
</Link>
</div>
{/* Buttons + bottom nav bar */}
<>
{/* Buttons */}
{loaded && navigation && (
<div className="opacity-0 group-hover/cardGallerySlider:opacity-100 transition-opacity ">
{index > 0 && (
<button
className="absolute w-8 h-8 left-3 top-[calc(50%-16px)] bg-white dark:bg-neutral-900 border border-neutral-200 dark:border-neutral-6000 dark:hover:border-neutral-500 rounded-full flex items-center justify-center hover:border-neutral-300 focus:outline-none"
style={{ transform: "translate3d(0, 0, 0)" }}
onClick={() => changePhotoId(index - 1)}
>
<ChevronLeftIcon className="h-4 w-4" />
</button>
)}
{index + 1 < images.length && (
<button
className="absolute w-8 h-8 right-3 top-[calc(50%-16px)] bg-white dark:bg-neutral-900 border border-neutral-200 dark:border-neutral-6000 dark:hover:border-neutral-500 rounded-full flex items-center justify-center hover:border-neutral-300 focus:outline-none"
style={{ transform: "translate3d(0, 0, 0)" }}
onClick={() => changePhotoId(index + 1)}
>
<ChevronRightIcon className="h-4 w-4" />
</button>
)}
</div>
)}
{/* Bottom Nav bar */}
<div className="absolute bottom-0 inset-x-0 h-10 bg-gradient-to-t from-neutral-900 opacity-50 rounded-b-lg"></div>
<div className="flex items-center justify-center absolute bottom-2 left-1/2 transform -translate-x-1/2 space-x-1.5">
{images.map((_, i) => (
<button
className={`w-1.5 h-1.5 rounded-full ${
i === index ? "bg-white" : "bg-white/60 "
}`}
onClick={() => changePhotoId(i)}
key={i}
/>
))}
</div>
</>
</div>
</MotionConfig>
);
}
Loading…
Cancel
Save