Skip to content
Components

Marquee

Marquee brings controlled expression to your interface.

Open ↗

Make it yours.

Install the editable source and its dependencies into your React + Tailwind project.

Scroll horizontally for long lines
pnpm dlx shadcn@4.0.8 add http://localhost:3000/r/marquee.json

Use it

Scroll horizontally for long lines
"use client";
import {Marquee} from '@/components/jez-ui/ui/marquee';

export default function Example(){

return <><Marquee><span className="font-display text-4xl">MAKE ROOM.</span><span className="font-display text-4xl">MAKE SOMETHING.</span><span className="font-display text-4xl">MAKE IT YOURS.</span></Marquee></>;
}

Props & types

Scroll horizontally for long lines
{
  children: React.ReactNode;
  duration?: number;
  className?: string;
}

Source

View 2 source files

registry/ui/marquee.tsx

Scroll horizontally for long lines
"use client";
import * as React from "react";
import { cn } from "./utils";
export function Marquee({
  children,
  duration = 24,
  className,
}: {
  children: React.ReactNode;
  duration?: number;
  className?: string;
}) {
  const [paused, setPaused] = React.useState(false);
  return (
    <div className={cn("overflow-hidden", className)}>
      <div
        className="flex w-max gap-10"
        style={{
          animation: `jez-marquee ${duration}s linear infinite`,
          animationPlayState: paused ? "paused" : "running",
        }}
        onPointerEnter={() => setPaused(true)}
        onPointerLeave={() => setPaused(false)}
      >
        <div className="flex shrink-0 gap-10">{children}</div>
        <div aria-hidden="true" inert className="flex shrink-0 gap-10">
          {children}
        </div>
      </div>
      <button
        onClick={() => setPaused((v) => !v)}
        className="mt-4 text-xs underline"
      >
        {paused ? "Resume" : "Pause"} animation
      </button>
    </div>
  );
}

registry/ui/utils.ts

Scroll horizontally for long lines
import { clsx, type ClassValue } from "clsx";
import { twMerge } from "tailwind-merge";
export function cn(...values: ClassValue[]) {
  return twMerge(clsx(values));
}

Dependencies

clsx@2.1.1 · tailwind-merge@3.5.0

Accessibility & behaviour

Respect reduced-motion preferences. Decorative effects must not carry essential information. WebGL scenes include a static fallback and only render while visible.

Read the accessibility and performance guide →