{ "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "marquee-testimonials", "title": "Marquee Testimonials", "description": "Infinite-scroll horizontal testimonial strip with optional double row", "files": [ { "path": "registry/pioneerui/marquee-testimonials.tsx", "content": "\"use client\"\n\nimport React from \"react\"\nimport { cn } from \"@/lib/utils\"\n\nexport interface MarqueeTestimonialItem {\n quote: string\n name: string\n role?: string\n company?: string\n avatar?: string\n}\n\nexport interface MarqueeTestimonialsProps extends React.HTMLAttributes {\n items: MarqueeTestimonialItem[]\n speed?: number\n pauseOnHover?: boolean\n reverse?: boolean\n rows?: 1 | 2\n}\n\nfunction TestimonialChip({ item }: { item: MarqueeTestimonialItem }) {\n return (\n
\n

\n “{item.quote}”\n

\n
\n {item.avatar ? (\n \n ) : (\n
\n {item.name.charAt(0)}\n
\n )}\n
\n

{item.name}

\n {(item.role || item.company) && (\n

\n {item.role}\n {item.role && item.company ? \" ยท \" : \"\"}\n {item.company}\n

\n )}\n
\n
\n
\n )\n}\n\ninterface RowProps {\n items: MarqueeTestimonialItem[]\n duration: string\n reverse?: boolean\n pauseOnHover?: boolean\n}\n\nfunction MarqueeRow({ items, duration, reverse, pauseOnHover }: RowProps) {\n return (\n \n {[0, 1].map((key) => (\n \n {items.map((item, i) => (\n \n ))}\n \n ))}\n \n )\n}\n\nexport function MarqueeTestimonials({\n items,\n speed = 30,\n pauseOnHover = true,\n reverse = false,\n rows = 1,\n className,\n ...props\n}: MarqueeTestimonialsProps) {\n // --duration drives the built-in `marquee` Tailwind animation keyframe\n const duration = `${(items.length * 80) / speed}s`\n\n return (\n \n {/* Edge fade masks */}\n
\n
\n\n
\n \n {rows === 2 && (\n \n )}\n
\n
\n )\n}\n", "type": "registry:ui", "target": "components/pioneerui/marquee-testimonials.tsx" } ], "type": "registry:ui" }