42 lines
1.2 KiB
TypeScript
42 lines
1.2 KiB
TypeScript
/**
|
|
* Horizontal running ticker of research keywords (magazine masthead style).
|
|
* Pure CSS animation (see tailwind `animate-marquee`). The track is rendered
|
|
* twice so the -50% translate loops seamlessly.
|
|
*
|
|
* CUSTOMIZATION HOOK — CONTENT: pass your own `items`.
|
|
* CUSTOMIZATION HOOK — MOTION: `reverse` flips direction; speed via tailwind.
|
|
*/
|
|
export default function Marquee({
|
|
items,
|
|
reverse = false,
|
|
className = "",
|
|
}: {
|
|
items: string[];
|
|
reverse?: boolean;
|
|
className?: string;
|
|
}) {
|
|
const sep = "✦";
|
|
const sequence = [...items];
|
|
|
|
return (
|
|
<div className={`w-full max-w-full overflow-hidden ${className}`} aria-hidden>
|
|
<div
|
|
className={`marquee-track w-max ${
|
|
reverse ? "animate-marquee-reverse" : "animate-marquee"
|
|
}`}
|
|
>
|
|
{[0, 1].map((dup) => (
|
|
<span key={dup} className="flex shrink-0">
|
|
{sequence.map((item, i) => (
|
|
<span key={`${dup}-${i}`} className="flex items-center">
|
|
<span className="px-6">{item}</span>
|
|
<span className="text-vermillion">{sep}</span>
|
|
</span>
|
|
))}
|
|
</span>
|
|
))}
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|