diff --git a/src/components/community-pages/carousel.tsx b/src/components/community-pages/carousel.tsx deleted file mode 100644 index 3fc66d40..00000000 --- a/src/components/community-pages/carousel.tsx +++ /dev/null @@ -1,88 +0,0 @@ -import { useState, useMemo } from "react"; -import { Autoplay } from "swiper/modules"; -import { Swiper, SwiperSlide } from "swiper/react"; -import "swiper/css"; - -const images = [ - "/images/slides/slide1.webp", - "/images/slides/slide2.webp", - "/images/slides/slide3.webp", - "/images/slides/slide4.webp", - "/images/slides/slide5.webp", - "/images/slides/slide6.webp", - "/images/slides/slide7.webp", - "/images/slides/slide8.webp", - "/images/slides/slide1.webp", - "/images/slides/slide2.webp", - "/images/slides/slide3.webp", - "/images/slides/slide4.webp", - "/images/slides/slide5.webp", - "/images/slides/slide6.webp", - "/images/slides/slide7.webp", - "/images/slides/slide8.webp", -]; - -const Carousel = () => { - const memoizedImages = useMemo(() => images, []); - - const [isLoaded, setIsLoaded] = useState(false); - - return ( -
- setIsLoaded(true)} - > - {memoizedImages.map((src, index) => ( - -
- {`Carousel -
-
- ))} -
-
- ); -}; - -export default Carousel; diff --git a/src/components/community-pages/custom-carousel/Carousel.css b/src/components/community-pages/custom-carousel/Carousel.css new file mode 100644 index 00000000..94fcd575 --- /dev/null +++ b/src/components/community-pages/custom-carousel/Carousel.css @@ -0,0 +1,42 @@ +.carousel-container { + position: relative; + width: 100%; + overflow: hidden; +} + +.carousel-track { + display: flex; + width: fit-content; + will-change: transform; +} + +@keyframes smooth-scroll { + from { + transform: translateX(0); + } + to { + transform: translateX(calc(-1 * var(--scroll-width))); + } +} + +.animate-scroll { + animation: smooth-scroll var(--animation-duration) linear infinite; + animation-fill-mode: forwards; +} + +.carousel-track { + width: fit-content; + will-change: transform; +} + +.carousel-item img { + max-width: 100%; + height: auto; +} + +@media (min-width: 768px) { + .carousel-item img { + height: 100%; + object-fit: cover; + } +} diff --git a/src/components/community-pages/custom-carousel/Carousel.tsx b/src/components/community-pages/custom-carousel/Carousel.tsx new file mode 100644 index 00000000..14f83ce4 --- /dev/null +++ b/src/components/community-pages/custom-carousel/Carousel.tsx @@ -0,0 +1,38 @@ +import React from "react"; +import { CarouselItem } from "./CarouselItem"; +import { useCarousel } from "./useCarousel"; +import type { CarouselProps } from "./types"; +import "./Carousel.css"; + +export const Carousel: React.FC = ({ + images, + speed = 50, + gap = 20, +}) => { + const { containerRef, trackRef, isLoaded } = useCarousel(speed); + + const displayImages = [...images, ...images, ...images]; + + return ( +
+
+ {displayImages.map((image, index) => ( + + ))} +
+
+ ); +}; diff --git a/src/components/community-pages/custom-carousel/CarouselItem.tsx b/src/components/community-pages/custom-carousel/CarouselItem.tsx new file mode 100644 index 00000000..ae8386d2 --- /dev/null +++ b/src/components/community-pages/custom-carousel/CarouselItem.tsx @@ -0,0 +1,31 @@ +import React from 'react'; + +interface CarouselItemProps { + src: string; + alt: string; + isLoaded: boolean; +} + +export const CarouselItem: React.FC = ({ src, alt, isLoaded }) => ( +
+ {alt} +
+); \ No newline at end of file diff --git a/src/components/community-pages/custom-carousel/types.ts b/src/components/community-pages/custom-carousel/types.ts new file mode 100644 index 00000000..04a9ccb7 --- /dev/null +++ b/src/components/community-pages/custom-carousel/types.ts @@ -0,0 +1,10 @@ +export interface CarouselImage { + src: string; + alt: string; +} + +export interface CarouselProps { + images: CarouselImage[]; + speed?: number; + gap?: number; +} diff --git a/src/components/community-pages/custom-carousel/useCarousel.ts b/src/components/community-pages/custom-carousel/useCarousel.ts new file mode 100644 index 00000000..ab410865 --- /dev/null +++ b/src/components/community-pages/custom-carousel/useCarousel.ts @@ -0,0 +1,50 @@ +import { useEffect, useRef, useState } from "react"; + +export const useCarousel = (speed = 50) => { + const [isLoaded, setIsLoaded] = useState(false); + const containerRef = useRef(null); + const trackRef = useRef(null); + + useEffect(() => { + const track = trackRef.current; + if (!track) return; + + const images = Array.from(track.getElementsByTagName("img")); + Promise.all( + images.map( + (img) => + new Promise((resolve) => { + if (img.complete) resolve(null); + img.onload = () => resolve(null); + img.onerror = () => resolve(null); + }), + ), + ).then(() => { + setIsLoaded(true); + }); + }, []); + + useEffect(() => { + if (!isLoaded) return; + + const track = trackRef.current; + if (!track) return; + + const totalWidth = track.scrollWidth; + const duration = totalWidth / speed; + + track.style.setProperty("--scroll-width", `${totalWidth}px`); + track.style.setProperty("--animation-duration", `${duration}s`); + track.classList.add("animate-scroll"); + + return () => { + track.classList.remove("animate-scroll"); + }; + }, [isLoaded, speed]); + + return { + containerRef, + trackRef, + isLoaded, + }; +}; diff --git a/src/pages/community/akash-insiders.astro b/src/pages/community/akash-insiders.astro index faa6a882..5b29fc23 100644 --- a/src/pages/community/akash-insiders.astro +++ b/src/pages/community/akash-insiders.astro @@ -1,10 +1,20 @@ --- -import Carousel from "@/components/community-pages/carousel"; +import { Carousel } from "@/components/community-pages/custom-carousel/Carousel"; import PointerSection from "@/components/community-pages/pointer-section.astro"; import CommunityHero from "@/components/mdx-cards/community-hero.astro"; import ButtonLink from "@/components/ui/button-link.astro"; import TopMargin from "@/components/ui/top-margin.astro"; import Layout from "@/layouts/layout.astro"; +const images = [ + { src: "/images/slides/slide1.webp", alt: "Slide 1" }, + { src: "/images/slides/slide2.webp", alt: "Slide 2" }, + { src: "/images/slides/slide3.webp", alt: "Slide 3" }, + { src: "/images/slides/slide4.webp", alt: "Slide 4" }, + { src: "/images/slides/slide5.webp", alt: "Slide 5" }, + { src: "/images/slides/slide6.webp", alt: "Slide 6" }, + { src: "/images/slides/slide7.webp", alt: "Slide 7" }, + { src: "/images/slides/slide8.webp", alt: "Slide 8" }, +]; ---
- +