About
Two shelves of quote cards drifting in opposite directions. Each company wordmark is set in its own type voice; point at a card and it comes forward while the rest step back. From the Midnight template.
Built with React and Tailwind. Copy the prompt and paste it into Claude Code, Cursor or Lovable: your agent adds Testimonials Marquee to your project and fits it to your theme.
Code
How Testimonials Marquee is used: the demo's code. The component's own source comes with a free account.
Usage.tsx
import type { CSSProperties } from "react"
import { TestimonialMarquee } from "@/components/ui/testimonial-marquee"
const fonts =
"@import url('https://fonts.googleapis.com/css2?family=Fraunces:ital,opsz,wght,SOFT@0,9..144,300..600,0..100;1,9..144,300..600,0..100&family=Geist:wght@400..600&family=Geist+Mono:wght@400..500&display=swap');"
const settings = {
label: "Customers",
title: "Loved by teams who ship.",
duration: 210,
background: "#f7f5f0",
card: "#ffffff",
text: "#141a2e",
muted: "#4a5166",
primary: "#a8803a",
primaryText: "#ffffff",
}
// Midnight by day as theme tokens: warm paper, night-blue ink, deep gold with white text on it,
// Fraunces for headings, Geist for text, Geist Mono for figures. The component itself only reads the tokens.
function day(s: typeof settings) {
const t: Record<string, string> = {
background: s.background,
foreground: s.text,
card: s.card,
primary: s.primary,
"primary-foreground": s.primaryText,
"muted-foreground": s.muted,
}
return {
...Object.fromEntries(Object.entries(t).flatMap(([k, v]) => [[`--${k}`, v], [`--color-${k}`, v]])),
"--font-display": "Fraunces, ui-serif, Georgia, serif",
"--font-sans": "Geist, ui-sans-serif, system-ui, sans-serif",
"--font-mono": "'Geist Mono', ui-monospace, Menlo, monospace",
} as CSSProperties
}
const items = [
{ quote: "We moved our launch page over in an afternoon. The copy was the only thing we had to write.", name: "Ava Lindqvist", role: "Founder", company: "Brightwell" },
{ quote: "Our designers stopped redrawing the same pricing table every quarter.", name: "Jonas Weber", role: "Design Lead", company: "Coreline" },
{ quote: "It reads our theme, so it looked like us on the first render.", name: "Mei Tanaka", role: "Frontend Engineer", company: "Halcyon" },
{ quote: "Sign-ups went up the week we shipped the new page. We changed nothing else.", name: "Diego Ramos", role: "Growth", company: "Pinecrest" },
{ quote: "Clean code, sensible props, no surprises in review.", name: "Sara Okafor", role: "Staff Engineer", company: "Lumen" },
{ quote: "The phone layout is the part I did not expect to like this much.", name: "Tom Hughes", role: "Product Manager", company: "Northwind" },
{ quote: "We swapped the colours and it became a different product. That is the point.", name: "Nina Petrova", role: "CTO", company: "Verity" },
{ quote: "Docs in the code, not in a wiki nobody opens.", name: "Arjun Mehta", role: "Tech Lead", company: "Tallow" },
]
export default function Demo(props: Partial<typeof settings>) {
const s = { ...settings, ...props }
return (
<div
className="flex min-h-svh w-full flex-col justify-center overflow-x-clip py-16"
style={{ ...day(s), fontFamily: "Geist, ui-sans-serif, system-ui, sans-serif", background: s.background, color: s.text } as CSSProperties}
>
<style>{fonts}</style>
<div className="px-6 text-center">
<p className="flex items-center gap-2 text-[12px] leading-4 tracking-[0.16em] uppercase justify-center" style={{ fontFamily: "var(--font-mono)", color: "#8a6a2e" }}>
<svg viewBox="-6 -6 12 12" className="size-2.5" aria-hidden="true">
<path d="M0 -6Q0 0 6 0Q0 0 0 6Q0 0 -6 0Q0 0 0 -6Z" fill="currentColor" />
</svg>
{s.label}
</p>
<h2
className="mt-5 text-[40px] leading-[1.04] font-[350] tracking-[-0.02em] text-balance md:text-[56px]"
style={{ fontFamily: "var(--font-display)", fontVariationSettings: '"SOFT" 50' }}
>
{s.title}
</h2>
</div>
<TestimonialMarquee items={items} duration={s.duration} className="mt-8" />
</div>
)
}
















