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.
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
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>
)
}
"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>
)
}