Marquee
An infinite, edge-faded horizontal scroller for logos, tags or testimonials. Pauses on hover.
AccordionDialogTooltipSidebarCommandToastCarouselAccordionDialogTooltipSidebarCommandToastCarousel
components/ui/marquee.tsx
import * as React from "react";
export interface MarqueeProps {
children: React.ReactNode;
duration?: number;
pauseOnHover?: boolean;
className?: string;
}
export function Marquee({ children, duration = 24, pauseOnHover = true, className = "" }: MarqueeProps) {
return (
<div
className={[
"group w-full overflow-hidden",
"[mask-image:linear-gradient(90deg,transparent,black_15%,black_85%,transparent)]",
className,
].join(" ")}
>
<style>{"@keyframes nice-marquee{to{transform:translateX(calc(-50% - 6px))}}"}</style>
<div
className={["flex w-max gap-3", pauseOnHover ? "group-hover:[animation-play-state:paused]" : ""].join(" ")}
style={{ animation: "nice-marquee " + duration + "s linear infinite" }}
>
{children}
<div aria-hidden className="contents">
{children}
</div>
</div>
</div>
);
}Installation
01
Install with the shadcn CLI.
$ npx shadcn@latest add https://niceui.dev/r/marquee.json02
Or copy the source manually into components/ui/marquee.tsx. No extra dependencies.
Usage
import { Marquee } from "@/components/ui/marquee";
const tags = ["Accordion", "Dialog", "Tooltip", "Sidebar", "Command", "Toast"];
export default function Example() {
return (
<Marquee>
{tags.map((tag) => (
<span key={tag} className="rounded-lg border border-white/15 px-3.5 py-2 text-sm">
{tag}
</span>
))}
</Marquee>
);
}For AI assistants
This page is also available as Markdown and as a shadcn registry item. Use Copy prompt to hand the full source to Claude, Cursor or v0.