Items that scroll on their own and loop without a seam: logos, testimonials, integrations, a news or price ticker — sideways or up.
$ pnpm dlx shadcn@latest add https://dashral.com/r/marquee.jsonInstallation
$ pnpm dlx shadcn@latest add https://dashral.com/r/marquee.jsonAdds the component, the components it builds on, its npm packages and the theme tokens it uses. Using Dashral often? Add the registry to components.json once:
{
"registries": {
"@dashral": "https://dashral.com/r/{name}.json"
}
}Then add components by name:
$ pnpm dlx shadcn@latest add @dashral/marqueeUsage
import { Marquee } from "@/components/dashral/marquee"
<Marquee pauseOnHover fade aria-label="Customers">
{["Acme", "Globex", "Initech", "Umbrella"].map((name) => (
<span key={name} className="text-lg font-semibold">
{name}
</span>
))}
</Marquee>Examples
Vertical columns
vertical scrolls up (down with reverse); give it a height. Each column at its own speed.
API reference
Marquee
Also takes every prop of <div>(opens in a new tab).
| Prop | Type | Default |
|---|---|---|
children | ReactNodeThe items; they're repeated as often as it takes to fill the strip. Required. | — |
speed | numberPixels per second. | 40 |
reverse | booleanThe other way: rightward (leftward in right-to-left text), or downward when vertical. | false |
vertical | booleanScrolls up instead of sideways. Give it a height. | false |
pauseOnHover | booleanStops while the pointer is over it or focus is inside it. | false |
fade | booleanFades the items out at both ends. | false |
gap | stringSpace between items, and between one copy of them and the next: any CSS length. | "1rem" |
aria-label | stringNames the strip (it becomes a region), e.g. "Customers". | — |
classNames | { track?, group? }Classes for the moving strip and each copy of the items. | — |
className | stringExtra classes, merged with cn() so yours win. | — |
Accessibility
- The items are in the page once for screen readers and the keyboard: the copies that make the loop seamless are aria-hidden and inert.
- With pauseOnHover it stops while focus is inside, so a link or button in it can be reached and read before it moves on.
- Give it an aria-label when the items need a name as a group, e.g. a list of customers.
Motion
- It moves at a constant speed, in pixels per second, by exactly one copy of the items, so the loop has no seam; it runs on the Web Animations API, with no CSS to add. With reduced motion it holds still and scrolls by hand.