diff --git a/app/(website)/_components/ClientLogosSection.tsx b/app/(website)/_components/ClientLogosSection.tsx index 7a1b79f..c57131f 100644 --- a/app/(website)/_components/ClientLogosSection.tsx +++ b/app/(website)/_components/ClientLogosSection.tsx @@ -1,42 +1,85 @@ -// components/ClientLogosSection.tsx -import React from "react"; +"use client"; + +import { useRef, useEffect, useState } from "react"; import Image from "next/image"; -// Define structure for client data - focusing on logos now type Client = { name: string; - logoUrl: string; // Expecting actual logo URLs now + logoUrl: string; }; type ClientLogosSectionProps = { title: string; description?: string; clients: Client[]; - /** Control animation speed (lower number = faster). Default: 40s */ - speed?: number; - /** Size of the square background container in pixels. Default: 120 */ + speed?: number; // pixels per frame squareSize?: number; }; -const ClientLogosSection: React.FC = ({ +const ClientLogosSection = ({ title, description, - clients = [], // Default to empty array - speed = 40, //Default speed in seconds for one full cycle - squareSize = 120, // Default size for the square container (e.g., 120px) -}) => { - // Need at least one client to render the marquee - if (clients.length === 0) { - return null; // Or render a placeholder message if preferred - } + clients = [], + speed = 1, + squareSize = 120, +}: ClientLogosSectionProps) => { + if (clients.length === 0) return null; - // Duplicate the clients for a seamless loop effect const extendedClients = [...clients, ...clients]; - - const squareDim = `${squareSize}px`; // Convert size to string for inline style - const padding = Math.round(squareSize / 6); // Calculate padding based on size (adjust divisor as needed) + const squareDim = `${squareSize}px`; + const padding = Math.round(squareSize / 6); const paddingDim = `${padding}px`; + const scrollRef = useRef(null); + const [direction, setDirection] = useState<"left" | "right">("left"); + const [paused, setPaused] = useState(false); + let resumeTimeout: NodeJS.Timeout; + + const pauseAndScroll = (dir: "left" | "right") => { + if (!scrollRef.current) return; + + setPaused(true); + + // Scroll manually + scrollRef.current.scrollBy({ + left: dir === "left" ? -200 : 200, + behavior: "smooth", + }); + + // Clear previous timeout and resume after 3 seconds + clearTimeout(resumeTimeout); + resumeTimeout = setTimeout(() => { + setPaused(false); + }, 3000); + + // Set the direction for automatic scroll after pause + setDirection(dir === "left" ? "right" : "left"); + }; + + useEffect(() => { + const container = scrollRef.current; + if (!container) return; + + let animationFrame: number; + + const step = () => { + if (!paused) { + if (direction === "left") { + container.scrollLeft += speed; + if (container.scrollLeft >= container.scrollWidth / 2) container.scrollLeft = 0; + } else { + container.scrollLeft -= speed; + if (container.scrollLeft <= 0) container.scrollLeft = container.scrollWidth / 2; + } + } + animationFrame = requestAnimationFrame(step); + }; + + animationFrame = requestAnimationFrame(step); + + return () => cancelAnimationFrame(animationFrame); + }, [direction, paused, speed]); + return (
@@ -45,19 +88,17 @@ const ClientLogosSection: React.FC = ({
- {/* Marquee container - group allows pausing animation on hover */} -
- {/* Inner container that will animate */} + {/* Logos Container */} +
{extendedClients.map((client, index) => (
- {/* Square Background Container */}
))}
+
- {/* Optional: Add fade effect at the edges */} -
-
+ {/* Arrow Controls */} +
+ +
{description && ( diff --git a/app/globals.css b/app/globals.css index a86238e..2aad820 100644 --- a/app/globals.css +++ b/app/globals.css @@ -208,18 +208,16 @@ } /* Added longer delay */ } -@keyframes fadeInUp { - from { - opacity: 0; - transform: translateY(20px); - } - to { - opacity: 1; - transform: translateY(0); - } + +@keyframes marquee { + from { transform: translateX(0); } + to { transform: translateX(-50%); } } -.animate-fade-in-up { - animation: fadeInUp 0.8s ease-out forwards; - opacity: 0; /* Start hidden */ +.animate-marquee-continuous { + animation: marquee linear infinite; +} + +.paused { + animation-play-state: paused !important; }