Logos Carousel
Original · freelogo carousel strip
byWeb InnoventixReact + Tailwind
carlogoscarousels
Copy prompt gives Claude Code, Cursor or v0 a ready-to-paste prompt that recreates this exact component.
npx shadcn@latest add https://webinnoventix.com/r/car-logos.jsoncar-logos.tsx
"use client";
import { useState, type ReactNode } from "react";
import { motion, useReducedMotion } from "motion/react";
type Logo = {
name: string;
sector: string;
Icon: (props: { className?: string }) => ReactNode;
};
const LOGOS: Logo[] = [
{
name: "Northwind Freight",
sector: "Logistics",
Icon: ({ className }) => (
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth={1.75} strokeLinecap="round" strokeLinejoin="round" className={className} aria-hidden="true">
<path d="M3 8h11a2.5 2.5 0 1 0-2.5-2.5" />
<path d="M3 12h15a2.5 2.5 0 1 1-2.5 2.5" />
<path d="M3 16h8" />
</svg>
),
},
{
name: "Lumen Analytics",
sector: "Data",
Icon: ({ className }) => (
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth={1.75} strokeLinecap="round" strokeLinejoin="round" className={className} aria-hidden="true">
<circle cx="12" cy="12" r="3.5" />
<path d="M12 2.5v2.5M12 19v2.5M2.5 12H5M19 12h2.5M5.2 5.2l1.8 1.8M17 17l1.8 1.8M18.8 5.2 17 7M7 17l-1.8 1.8" />
</svg>
),
},
{
name: "Cedarline",
sector: "Sustainability",
Icon: ({ className }) => (
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth={1.75} strokeLinecap="round" strokeLinejoin="round" className={className} aria-hidden="true">
<path d="M12 3 6.5 11h11z" />
<path d="M12 8 5 17h14z" />
<path d="M12 17v4" />
</svg>
),
},
{
name: "Quanta Robotics",
sector: "Hardware",
Icon: ({ className }) => (
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth={1.75} strokeLinecap="round" strokeLinejoin="round" className={className} aria-hidden="true">
<path d="M12 3 20 7.5v9L12 21 4 16.5v-9z" />
<circle cx="12" cy="12" r="2.4" />
</svg>
),
},
{
name: "Meridian Health",
sector: "Healthcare",
Icon: ({ className }) => (
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth={1.75} strokeLinecap="round" strokeLinejoin="round" className={className} aria-hidden="true">
<circle cx="12" cy="12" r="8.5" />
<path d="M12 8v8M8 12h8" />
</svg>
),
},
{
name: "Halcyon Studios",
sector: "Media",
Icon: ({ className }) => (
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth={1.75} strokeLinecap="round" strokeLinejoin="round" className={className} aria-hidden="true">
<path d="M3 9c3-3 6 3 9 0s6 3 9 0" />
<path d="M3 15c3-3 6 3 9 0s6 3 9 0" />
</svg>
),
},
{
name: "Ironpeak Capital",
sector: "Finance",
Icon: ({ className }) => (
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth={1.75} strokeLinecap="round" strokeLinejoin="round" className={className} aria-hidden="true">
<path d="M3 19 10 8l3 4 3-5 5 12z" />
</svg>
),
},
{
name: "Sable Coffee",
sector: "Retail",
Icon: ({ className }) => (
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth={1.75} strokeLinecap="round" strokeLinejoin="round" className={className} aria-hidden="true">
<path d="M6 9h9v3.5a4 4 0 0 1-4 4H10a4 4 0 0 1-4-4z" />
<path d="M15 10h1.8a2 2 0 1 1 0 4H15" />
<path d="M9 3.5v2M12 3.5v2" />
</svg>
),
},
{
name: "Vireo Cloud",
sector: "Infrastructure",
Icon: ({ className }) => (
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth={1.75} strokeLinecap="round" strokeLinejoin="round" className={className} aria-hidden="true">
<path d="M5 19C5 11 11 5 19 5c0 8-6 14-14 14z" />
<path d="M9 15 15 9" />
</svg>
),
},
];
export default function CarLogos() {
const reduce = useReducedMotion();
const [playing, setPlaying] = useState<boolean>(true);
const [reverse, setReverse] = useState<boolean>(false);
const [speed, setSpeed] = useState<number>(3);
const [hovered, setHovered] = useState<boolean>(false);
const duration = 70 / speed;
const paused = reduce || !playing || hovered;
const pillBase =
"inline-flex items-center gap-2 rounded-full border px-4 py-2 text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-indigo-500 focus-visible:ring-offset-2 focus-visible:ring-offset-slate-50 dark:focus-visible:ring-offset-slate-950 disabled:cursor-not-allowed disabled:opacity-50";
const pillIdle =
" border-slate-200 bg-white text-slate-700 hover:bg-slate-100 dark:border-slate-700 dark:bg-slate-900 dark:text-slate-200 dark:hover:bg-slate-800";
const pillActive =
" border-indigo-600 bg-indigo-600 text-white hover:bg-indigo-500 dark:border-indigo-500 dark:bg-indigo-500 dark:text-white dark:hover:bg-indigo-400";
const renderList = (hidden: boolean) => (
<ul
className="flex shrink-0 list-none items-center gap-x-12"
aria-hidden={hidden || undefined}
aria-label={hidden ? undefined : "Our partners and integrations"}
>
{LOGOS.map((logo) => (
<li key={(hidden ? "dup-" : "") + logo.name} className="group flex shrink-0 items-center gap-3">
<span className="text-slate-300 transition-colors duration-300 group-hover:text-indigo-500 dark:text-slate-600 dark:group-hover:text-indigo-400">
{logo.Icon({ className: "h-7 w-7" })}
</span>
<span className="text-lg font-semibold tracking-tight text-slate-400 transition-colors duration-300 group-hover:text-slate-900 dark:text-slate-500 dark:group-hover:text-white">
{logo.name}
</span>
</li>
))}
</ul>
);
return (
<section className="relative w-full overflow-hidden bg-slate-50 py-24 dark:bg-slate-950 sm:py-28">
<style>{`
@keyframes carlogos-marquee {
from { transform: translateX(0); }
to { transform: translateX(-50%); }
}
@keyframes carlogos-pulse {
0%, 100% { transform: scale(1); opacity: 0.7; }
50% { transform: scale(2.2); opacity: 0; }
}
@media (prefers-reduced-motion: reduce) {
.carlogos-track { animation: none !important; transform: none !important; }
.carlogos-pulse { animation: none !important; }
}
`}</style>
<div className="mx-auto max-w-6xl px-6">
<motion.div
className="text-center"
initial={reduce ? false : { opacity: 0, y: 16 }}
whileInView={{ opacity: 1, y: 0 }}
viewport={{ once: true, margin: "-80px" }}
transition={{ duration: 0.6, ease: "easeOut" }}
>
<span className="inline-flex items-center gap-2 rounded-full border border-slate-200 bg-white px-3 py-1 text-xs font-medium uppercase tracking-widest text-slate-500 dark:border-slate-800 dark:bg-slate-900 dark:text-slate-400">
<span className="relative flex h-2 w-2">
<span
className="carlogos-pulse absolute inline-flex h-full w-full rounded-full bg-emerald-400"
style={reduce ? undefined : { animation: "carlogos-pulse 2s ease-in-out infinite" }}
/>
<span className="relative inline-flex h-2 w-2 rounded-full bg-emerald-500" />
</span>
Live ecosystem
</span>
<h2 className="mt-6 text-balance text-3xl font-bold tracking-tight text-slate-900 dark:text-white sm:text-4xl">
The tools your team already trusts, working as one
</h2>
<p className="mx-auto mt-4 max-w-2xl text-pretty text-base text-slate-600 dark:text-slate-300 sm:text-lg">
A live look at the partners, integrations, and clients moving through the platform every
day. Pause it, slow it down, or send it the other way.
</p>
</motion.div>
<div className="mt-10 flex flex-wrap items-center justify-center gap-3 sm:gap-4">
<button
type="button"
onClick={() => setPlaying((p) => !p)}
disabled={reduce ?? undefined}
className={pillBase + (playing && !reduce ? pillActive : pillIdle)}
>
{playing ? (
<svg viewBox="0 0 24 24" fill="currentColor" className="h-4 w-4" aria-hidden="true">
<rect x="6" y="5" width="4" height="14" rx="1" />
<rect x="14" y="5" width="4" height="14" rx="1" />
</svg>
) : (
<svg viewBox="0 0 24 24" fill="currentColor" className="h-4 w-4" aria-hidden="true">
<path d="M8 5v14l11-7z" />
</svg>
)}
{playing ? "Pause" : "Play"}
</button>
<button
type="button"
onClick={() => setReverse((r) => !r)}
disabled={reduce ?? undefined}
aria-pressed={reverse}
className={pillBase + (reverse && !reduce ? pillActive : pillIdle)}
>
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth={1.75} strokeLinecap="round" strokeLinejoin="round" className="h-4 w-4" aria-hidden="true">
<path d="M3 12h18" />
<path d="m6 9-3 3 3 3" />
<path d="m18 9 3 3-3 3" />
</svg>
Reverse
</button>
<div className="inline-flex items-center gap-3 rounded-full border border-slate-200 bg-white px-4 py-2 dark:border-slate-700 dark:bg-slate-900">
<label
htmlFor="carlogos-speed"
className="text-sm font-medium text-slate-700 dark:text-slate-200"
>
Speed
</label>
<span className="text-xs text-slate-400 dark:text-slate-500" aria-hidden="true">Slow</span>
<input
id="carlogos-speed"
type="range"
min={1}
max={5}
step={1}
value={speed}
onChange={(e) => setSpeed(Number(e.target.value))}
disabled={reduce ?? undefined}
aria-label="Scrolling speed"
aria-valuetext={`Speed ${speed} of 5`}
className="h-2 w-28 cursor-pointer appearance-none rounded-full bg-slate-200 accent-indigo-600 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-indigo-500 focus-visible:ring-offset-2 focus-visible:ring-offset-white disabled:cursor-not-allowed disabled:opacity-50 dark:bg-slate-700 dark:accent-indigo-400 dark:focus-visible:ring-offset-slate-900"
/>
<span className="text-xs text-slate-400 dark:text-slate-500" aria-hidden="true">Fast</span>
</div>
</div>
{reduce ? (
<p className="mt-4 text-center text-sm text-slate-500 dark:text-slate-400">
Reduced-motion is on, so the strip is paused. Scroll it sideways to browse.
</p>
) : null}
<div
className={
"relative mt-12 rounded-3xl border border-slate-200 bg-white py-8 dark:border-slate-800 dark:bg-slate-900 " +
(reduce ? "overflow-x-auto" : "overflow-hidden")
}
role="group"
aria-label="Logo carousel"
onMouseEnter={() => setHovered(true)}
onMouseLeave={() => setHovered(false)}
>
{!reduce ? (
<>
<div className="pointer-events-none absolute inset-y-0 left-0 z-10 w-16 rounded-l-3xl bg-gradient-to-r from-white to-transparent dark:from-slate-900 sm:w-28" />
<div className="pointer-events-none absolute inset-y-0 right-0 z-10 w-16 rounded-r-3xl bg-gradient-to-l from-white to-transparent dark:from-slate-900 sm:w-28" />
</>
) : null}
<div
className="carlogos-track flex w-max items-center gap-x-12 px-10"
style={
reduce
? undefined
: {
animationName: "carlogos-marquee",
animationDuration: `${duration}s`,
animationTimingFunction: "linear",
animationIterationCount: "infinite",
animationDirection: reverse ? "reverse" : "normal",
animationPlayState: paused ? "paused" : "running",
}
}
>
{renderList(false)}
{!reduce ? renderList(true) : null}
</div>
</div>
<p className="mt-6 text-center text-sm text-slate-500 dark:text-slate-400">
Plus 40+ more in the integration marketplace, added every week.
</p>
</div>
</section>
);
}Dependencies
motion
Licence
Built by Web Innoventix. Free for personal and commercial use, no attribution required.
Built by Web Innoventix
Need a custom interface, a full website, or SEO that gets you cited by AI? We design, build and rank it end to end.
Get a free quoteSimilar components
Browse all →
Basic Carousel
Originalbasic image carousel with arrows and dots

Fade Carousel
Originalcrossfade carousel

Cards Carousel
Originalpeeking card carousel

Coverflow Carousel
Original3D coverflow carousel
Thumbnails Carousel
Originalcarousel synced with thumbnails

Autoplay Carousel
Originalautoplay carousel with progress and pause

Dots Carousel
Originalcarousel with animated dot indicators

Vertical Carousel
Originalvertical carousel

Multi Carousel
Originalmulti-item responsive carousel

Center Focus Carousel
Originalcentre-focused scaling carousel

Progress Carousel
Originalcarousel with a progress bar

Testimonial Carousel
Originaltestimonial quote carousel

