All components

Logo Cloud 04

Logo Cloud 04 is a React and Tailwind CSS marquee component from Eldora UI, licensed MIT. Copy it and paste it into your project.

Eldora UI MIT marquee

What it is

Logo Cloud 04 is a React and Tailwind CSS marquee component from Eldora UI, licensed MIT. Copy it and paste it into your project.

How to use it

Open it in the catalogue, press copy, and paste it into your project. The prompt you copy carries the code and the rules that tell your agent to reproduce it without changing anything.

Open in the catalogue

Five free copies a month. No card.

Needs

npm i motion/react

Licence

This component comes from Eldora UI and is redistributed under the MIT licence, which permits commercial use. The copyright notice travels with the code.

Logo Cloud 04

registry/blocks/logo-cloud-04/page.tsx
import { LogoCarousel } from "@/registry/blocks/logo-cloud-04/components/logo-cloud-04"

// ensure to make equal number of logos
export function LogoCloud04() {
  return (
    <div className="flex min-h-svh w-full items-center justify-center p-6 md:p-10">
      <div className="w-full max-w-sm md:max-w-3xl">
        <section
          id="clients"
          className="mx-auto max-w-7xl px-6 text-center md:px-8"
        >
          <div className="py-14">
            <div className="mx-auto max-w-screen-xl px-4 md:px-8">
              <h2 className="text-center text-sm font-semibold text-gray-600">
                TRUSTED BY TEAMS FROM AROUND THE WORLD
              </h2>
              <LogoCarousel columns={3} />
            </div>
          </div>
        </section>
      </div>
    </div>
  )
}
registry/blocks/logo-cloud-04/components/logo-cloud-04.tsx
"use client"

import { useCallback, useEffect, useMemo, useRef, useState } from "react"

import { cn } from "@/lib/utils"

import { AnimatedLogoColumn, type Logo } from "./animated-logo-column"

const LOGOS: Logo[] = [
  {
    id: 1,
    name: "Google",
    src: "https://pub-b3533f2e1c954842824758490b95c9d5.r2.dev/Google.svg",
  },
  {
    id: 2,
    name: "GitHub",
    src: "https://pub-b3533f2e1c954842824758490b95c9d5.r2.dev/GitHub.svg",
  },
  {
    id: 3,
    name: "Amazon",
    src: "https://pub-b3533f2e1c954842824758490b95c9d5.r2.dev/Amazon.svg",
  },
  {
    id: 4,
    name: "Netflix",
    src: "https://pub-b3533f2e1c954842824758490b95c9d5.r2.dev/Netflix.svg",
  },
  {
    id: 5,
    name: "YouTube",
    src: "https://pub-b3533f2e1c954842824758490b95c9d5.r2.dev/YouTube.svg",
  },
  {
    id: 6,
    name: "Instagram",
    src: "https://pub-b3533f2e1c954842824758490b95c9d5.r2.dev/Instagram.svg",
  },
]

const TICK_MS = 100

/**
 * Deterministic distribution (no Math.random) so server and client
 * render the same columns and hydration matches.
 */
function distributeLogos(logos: Logo[], columnCount: number): Logo[][] {
  const result: Logo[][] = Array.from({ length: columnCount }, () => [])

  logos.forEach((logo, index) => {
    result[index % columnCount].push(logo)
  })

  const maxLength = Math.max(...result.map((col) => col.length))
  result.forEach((col, colIndex) => {
    while (col.length < maxLength) {
      col.push(logos[(col.length * columnCount + colIndex) % logos.length])
    }
  })

  return result
}

export type LogoCarouselVariant = "default" | "compact"

interface LogoCarouselProps {
  columns?: number
  logos?: Logo[]
  variant?: LogoCarouselVariant
  className?: string
}

export function LogoCarousel({
  columns = 4,
  logos: logosProp,
  variant = "default",
  className,
}: LogoCarouselProps) {
  const logos = useMemo(() => logosProp ?? LOGOS, [logosProp])
  const distribute = useCallback(
    (count: number) => distributeLogos(logos, count),
    [logos]
  )

  const [logoColumns, setLogoColumns] = useState<Logo[][]>(() =>
    distributeLogos(logos, columns)
  )
  const [time, setTime] = useState(0)
  const prevColumnsRef = useRef(columns)

  useEffect(() => {
    if (prevColumnsRef.current !== columns) {
      prevColumnsRef.current = columns
      setLogoColumns(distribute(columns))
    }
  }, [columns, distribute])

  useEffect(() => {
    const interval = setInterval(() => {
      setTime((prev) => prev + TICK_MS)
    }, TICK_MS)
    return () => clearInterval(interval)
  }, [])

  return (
    <div
      className={cn(
        "flex flex-wrap justify-center gap-6 py-8 sm:gap-8",
        className
      )}
    >
      {logoColumns.map((columnLogos, index) => (
        <AnimatedLogoColumn
          key={`col-${index}`}
          logos={columnLogos}
          columnIndex={index}
          currentTime={time}
          variant={variant}
        />
      ))}
    </div>
  )
}

Similar components