From 43d995bbc2a181e61dc6f821538ed6bce3d9565b Mon Sep 17 00:00:00 2001 From: sasha-astiadi Date: Fri, 19 Sep 2025 01:01:46 +0200 Subject: [PATCH] feat: add responsive carousel with mobile-optimized layout and controls --- src/components/ClickableGallery.tsx | 51 +++++++++++++++++++---------- src/hooks/useResponsiveCarousel.ts | 39 ++++++++++++++++++++++ 2 files changed, 73 insertions(+), 17 deletions(-) create mode 100644 src/hooks/useResponsiveCarousel.ts diff --git a/src/components/ClickableGallery.tsx b/src/components/ClickableGallery.tsx index 35e4365..b37159f 100644 --- a/src/components/ClickableGallery.tsx +++ b/src/components/ClickableGallery.tsx @@ -1,6 +1,7 @@ 'use client' -import { useEffect, useMemo, useState, useRef } from 'react' +import { useEffect, useMemo, useState } from 'react' +import { useResponsiveCarousel } from '@/hooks/useResponsiveCarousel'; import Image from 'next/image' import { motion, AnimatePresence } from 'framer-motion' import { wrap } from 'popmotion' @@ -24,16 +25,13 @@ const galleryItems = [ ] // 🔧 Carousel Config -const VISIBLE = 4 -const GAP = 300 // spacing for larger cards -const ROT_Y = 18 -const DEPTH = 210 -const SCALE_DROP = 0.12 -const AUTOPLAY_MS = 3200 +const VISIBLE = 4; +const AUTOPLAY_MS = 3200; export function ClickableGallery() { - const [active, setActive] = useState(0) - const [hovering, setHovering] = useState(false) + const [active, setActive] = useState(0); + const [hovering, setHovering] = useState(false); + const { GAP, ROT_Y, DEPTH, SCALE_DROP } = useResponsiveCarousel(); // autoplay useEffect(() => { @@ -59,7 +57,7 @@ export function ClickableGallery() { -
+

The future isn’t about more tools. It’s about one intelligent partner that can do it all. This is your gateway to creativity, automation, and discovery.

@@ -72,7 +70,7 @@ export function ClickableGallery() { onMouseEnter={() => setHovering(true)} onMouseLeave={() => setHovering(false)} > -
+
{indices.map((idx, i) => { @@ -119,7 +117,8 @@ export function ClickableGallery() {
{/* Arrows */} -
+ {/* Arrows */} +
-
+
- {/* Foreground pill */} -
+ {/* Foreground pill (Desktop) */} +
-
+ + {/* Text box (Mobile) */} +
+
+ + + + +
+
); diff --git a/src/hooks/useResponsiveCarousel.ts b/src/hooks/useResponsiveCarousel.ts new file mode 100644 index 0000000..bcb401e --- /dev/null +++ b/src/hooks/useResponsiveCarousel.ts @@ -0,0 +1,39 @@ +'use client' + +import { useState, useEffect } from 'react'; + +// 🔧 Carousel Config +const desktopConfig = { + GAP: 300, + ROT_Y: 18, + DEPTH: 210, + SCALE_DROP: 0.12, +}; + +const mobileConfig = { + GAP: 100, // Smaller gap for mobile + ROT_Y: 0, // Flatter view on mobile + DEPTH: 150, // Less depth + SCALE_DROP: 0.1, // Less aggressive scaling +}; + +export const useResponsiveCarousel = () => { + const [config, setConfig] = useState(desktopConfig); + + useEffect(() => { + const checkScreenSize = () => { + if (window.innerWidth < 768) { + setConfig(mobileConfig); + } else { + setConfig(desktopConfig); + } + }; + + checkScreenSize(); + window.addEventListener('resize', checkScreenSize); + + return () => window.removeEventListener('resize', checkScreenSize); + }, []); + + return config; +};