{"slug":"marquee","name":"Marquee","description":"Infinite horizontal or vertical scroll with pause-on-hover.","category":"motion","source_url":"https://beui.saura3h.xyz/r/marquee/raw","detail_url":"https://beui.saura3h.xyz/r/marquee","raw_url":"https://beui.saura3h.xyz/r/marquee/raw","page_url":"https://beui.saura3h.xyz/components/motion/marquee","dependencies":["react"],"internal":["@/components/motion/marquee","@/lib/utils"],"files":[{"path":"components/motion/marquee.tsx","type":"component","content":"import { Children, type ReactNode } from \"react\";\nimport { cn } from \"@/lib/utils\";\n\nexport interface MarqueeProps {\n  children: ReactNode;\n  direction?: \"left\" | \"right\" | \"up\" | \"down\";\n  speed?: number;\n  pauseOnHover?: boolean;\n  gap?: string;\n  className?: string;\n  fade?: boolean;\n}\n\nexport function Marquee({\n  children,\n  direction = \"left\",\n  speed = 30,\n  pauseOnHover = true,\n  gap = \"1rem\",\n  className,\n  fade = true,\n}: MarqueeProps) {\n  const vertical = direction === \"up\" || direction === \"down\";\n  const reverse = direction === \"right\" || direction === \"down\";\n  const items = Children.toArray(children);\n\n  return (\n    <div\n      className={cn(\n        \"group relative flex overflow-hidden\",\n        vertical ? \"flex-col\" : \"flex-row\",\n        fade && !vertical && \"[mask-image:linear-gradient(to_right,transparent,black_12%,black_88%,transparent)]\",\n        fade && vertical && \"[mask-image:linear-gradient(to_bottom,transparent,black_12%,black_88%,transparent)]\",\n        className,\n      )}\n      style={{ \"--gap\": gap } as React.CSSProperties}\n    >\n      {[0, 1].map((dup) => (\n        <div\n          key={dup}\n          aria-hidden={dup === 1}\n          style={{\n            animationDuration: `${speed}s`,\n            animationDirection: reverse ? \"reverse\" : \"normal\",\n            gap,\n          }}\n          className={cn(\n            \"flex shrink-0 items-center\",\n            vertical ? \"flex-col animate-marquee-vertical\" : \"flex-row animate-marquee\",\n            pauseOnHover && \"group-hover:[animation-play-state:paused]\",\n          )}\n        >\n          {items.map((child, i) => (\n            <div key={i} className=\"shrink-0\">\n              {child}\n            </div>\n          ))}\n        </div>\n      ))}\n    </div>\n  );\n}\n"},{"path":"components/previews/motion/marquee.preview.tsx","type":"preview","content":"\"use client\";\n\nimport { Marquee } from \"@/components/motion/marquee\";\n\nconst logos = [\"Vercel\", \"Linear\", \"Stripe\", \"Figma\", \"GitHub\", \"Notion\", \"Loom\", \"Raycast\"];\n\nexport function MarqueePreview() {\n  return (\n    <div className=\"w-full\">\n      <Marquee speed={25}>\n        {logos.map((l) => (\n          <div\n            key={l}\n            className=\"mx-4 flex h-12 items-center justify-center rounded-lg border border-(--color-border) bg-(--color-bg-elev) px-6 text-sm font-medium text-(--color-fg)\"\n          >\n            {l}\n          </div>\n        ))}\n      </Marquee>\n    </div>\n  );\n}\n"},{"path":"lib/utils.ts","type":"util","content":"import { clsx, type ClassValue } from \"clsx\"\nimport { twMerge } from \"tailwind-merge\"\n\nexport function cn(...inputs: ClassValue[]) {\n  return twMerge(clsx(inputs))\n}\n"}]}