Installation
Usage
import ClientCarouselShowcase from "@/components/ruixen/client-carousel-showcase";
// Text-based logos (default)
<ClientCarouselShowcase />
// With custom logo elements
const clients = [
{
name: "GitHub",
logo: <img src="/github.svg" alt="" className="h-6 w-auto" />,
},
{
name: "Vercel",
logo: <img src="/vercel.svg" alt="" className="h-5 w-auto" />,
},
{ name: "Linear" },
{ name: "Stripe" },
];
<ClientCarouselShowcase
clients={clients}
title="Backed by the best"
speed={25}
/>
// Reverse direction
<ClientCarouselShowcase reverse />Props
| Prop | Type | Default | Description |
|---|---|---|---|
title | string | "Trusted by leading teams" | Heading text above the marquee |
clients | ClientCarouselItem[] | 8 default company names | Array of client items |
speed | number | 30 | Seconds per full scroll cycle |
reverse | boolean | false | Reverse scroll direction |
className | string | - | Additional CSS classes |
ClientCarouselItem
| Property | Type | Description |
|---|---|---|
name | string | Client name (rendered as text if no logo provided) |
logo | React.ReactNode | Optional custom logo element (SVG, img, component) |
href | string | Optional link URL |
Features
- Infinite Drift: CSS
@keyframestranslates a doubled track from0to-50%— seamless loop with no JS timers or carousel libraries - Gradient Edge Masks:
mask-image: linear-gradient(...)fades the leading and trailing 8% to transparent — logos emerge from and dissolve into nothing - Pause on Hover:
animation-play-state: paused— the track freezes when your cursor enters, resumes when it leaves - Proximity Field: Unlike binary hover, the cursor creates a 200px gaussian field of influence. Logos respond proportionally to distance — closest gets
scale(1.12),translateY(-4px), full opacity. The smoothstep functiont²(3-2t)ensures zero-derivative at both ends for natural, artifact-free falloff - 60fps DOM Updates: Proximity calculations run via
mousemovewith directel.stylemutation — no React state re-renders, no requestAnimationFrame needed. CSStransition: 0.35shandles interpolation between frames - Speed & Direction Control:
speedprop controls cycle duration;reverseflips the drift direction - Text-Based Defaults: Default clients render as clean semibold text — pass custom
logoReactNodes for real brand logos - Zero Dependencies: No embla-carousel, no framer-motion, no next/image — pure CSS animation + minimal JS proximity math
- Accessibility: Semantic section,
aria-labelon linked logos, keyboard-focusable

