Logo Marquee
Infinite logo cloud with soft faded edges.
Trusted by fast-moving teams worldwide
Lumora
Vertexa
Orbital
Stackline
Northwave
Cubeform
Launchly
Keystone
Lumora
Vertexa
Orbital
Stackline
Northwave
Cubeform
Launchly
Keystone
components/ui/logo-marquee.tsx
"use client";
import { motion } from "motion/react";
import { Box, Command, Hexagon, Layers, Orbit, Rocket, Triangle, Waves } from "lucide-react";
import type { ReactNode } from "react";
type MarqueeProps = {
children: ReactNode;
/** Seconds for one full loop */
duration?: number;
reverse?: boolean;
className?: string;
};
export function Marquee({ children, duration = 30, reverse = false, className = "" }: MarqueeProps) {
return (
<div
className={`flex overflow-hidden [mask-image:linear-gradient(to_right,transparent,black_12%,black_88%,transparent)] ${className}`}
>
<motion.div
className="flex shrink-0 gap-12 pr-12"
animate={{ x: reverse ? ["-50%", "0%"] : ["0%", "-50%"] }}
transition={{ duration, repeat: Infinity, ease: "linear" }}
>
{children}
{children}
</motion.div>
</div>
);
}
const logos = [
{ name: "Lumora", icon: Hexagon },
{ name: "Vertexa", icon: Triangle },
{ name: "Orbital", icon: Orbit },
{ name: "Stackline", icon: Layers },
{ name: "Northwave", icon: Waves },
{ name: "Cubeform", icon: Box },
{ name: "Launchly", icon: Rocket },
{ name: "Keystone", icon: Command },
];
export default function Demo() {
return (
<div className="w-full max-w-4xl">
<p className="mb-8 text-center text-sm text-zinc-500">Trusted by fast-moving teams worldwide</p>
<Marquee>
{logos.map(({ name, icon: Icon }) => (
<div key={name} className="flex shrink-0 items-center gap-2 text-zinc-400 transition-colors hover:text-zinc-900">
<Icon className="size-6" strokeWidth={1.75} />
<span className="text-xl font-semibold tracking-tight">{name}</span>
</div>
))}
</Marquee>
</div>
);
}
Installation
Install the dependencies
$ npm i motion lucide-reactCopy the source into
components/ui/logo-marquee.tsxcomponents/ui/logo-marquee.tsx"use client"; import { motion } from "motion/react"; import { Box, Command, Hexagon, Layers, Orbit, Rocket, Triangle, Waves } from "lucide-react"; import type { ReactNode } from "react"; type MarqueeProps = { children: ReactNode; /** Seconds for one full loop */ duration?: number; reverse?: boolean; className?: string; }; export function Marquee({ children, duration = 30, reverse = false, className = "" }: MarqueeProps) { return ( <div className={`flex overflow-hidden [mask-image:linear-gradient(to_right,transparent,black_12%,black_88%,transparent)] ${className}`} > <motion.div className="flex shrink-0 gap-12 pr-12" animate={{ x: reverse ? ["-50%", "0%"] : ["0%", "-50%"] }} transition={{ duration, repeat: Infinity, ease: "linear" }} > {children} {children} </motion.div> </div> ); } const logos = [ { name: "Lumora", icon: Hexagon }, { name: "Vertexa", icon: Triangle }, { name: "Orbital", icon: Orbit }, { name: "Stackline", icon: Layers }, { name: "Northwave", icon: Waves }, { name: "Cubeform", icon: Box }, { name: "Launchly", icon: Rocket }, { name: "Keystone", icon: Command }, ]; export default function Demo() { return ( <div className="w-full max-w-4xl"> <p className="mb-8 text-center text-sm text-zinc-500">Trusted by fast-moving teams worldwide</p> <Marquee> {logos.map(({ name, icon: Icon }) => ( <div key={name} className="flex shrink-0 items-center gap-2 text-zinc-400 transition-colors hover:text-zinc-900"> <Icon className="size-6" strokeWidth={1.75} /> <span className="text-xl font-semibold tracking-tight">{name}</span> </div> ))} </Marquee> </div> ); }Use it
The file exports the component and a
Demoshowing typical usage. Import whichever you need.