Design
llms.txt digitalcrew.tech

Marketing

SocialProofTestimonials

A wall of customer quotes: TestimonialCards stacked in columns that scroll vertically at different speeds, fading out at the top and bottom.

Crew OSMarketingDigitalCrew.SocialProofTestimonials
SocialProofTestimonials · live · 1100px wideOpen

Guidelines#

Use it for the testimonials section of the landing page, under a SectionHeader. TestimonialCard also works alone.

What you provide: testimonials: { id, name, role, img, description }[], where description is a node (a <p>, with the key phrase highlighted; Crew OS's Highlight helper is p-1 py-0.5 font-medium dark:font-semibold text-secondary). Every three testimonials make one column, so give 6 or 9. TestimonialCard takes name, role, img, description and className. Crew OS's customer photos come from randomuser.me, which is unreachable here, so this preview uses generated initials.

Anatomy: 40px side padding, at most 750px tall, overflow-hidden; two columns from md, three from xl. Cards are rounded-xl, bg-accent, 16px padding, a hairline ring and soft shadow (a lighter ring in dark mode), 24px between quote and author. Quote text is text-primary/90, leading-relaxed; the author row has a 32px round photo, the name in font-medium and the role in text-xs text-primary/50. The top and bottom sixth (fifth from md) fade into background.

Behaviour: each column is a vertical Marquee (content repeated four times): 40s for the first, 60s the second, 30s the third. Hovering does not pause it, and there is no reduced-motion branch.

Don't put links in quotes, mix very long and very short quotes, or use fewer than six (columns run out).

Facts#

GroupMarketing
ProductCrew OS
Globalwindow.DigitalCrew.SocialProofTestimonials
Sourcedigitalcrew-orchestrator: components/testimonial-scroll.tsx
Import in the appimport { SocialProofTestimonials } from "@/components/testimonial-scroll";

API#

TypeScript declarations emitted from components/testimonial-scroll.tsx (the module also exports TestimonialCard, SocialProofTestimonials).

export interface TestimonialCardProps extends React.HTMLAttributes<HTMLDivElement> {
    name: string;
    role: string;
    img?: string;
    description: React.ReactNode;
    className?: string;
}
export declare const TestimonialCard: ({ description, name, img, role, className, ...props }: TestimonialCardProps) => JSX.Element;
interface Testimonial {
    id: string;
    name: string;
    role: string;
    img: string;
    description: React.ReactNode;
}
export declare function SocialProofTestimonials({ testimonials, }: {
    testimonials: Testimonial[];
}): JSX.Element;

Example#

The code of the preview above: plain React.createElement against window.DigitalCrew, with realistic data.

<div id="root" class="p-6"></div>
<script>
(function () {
  var h = React.createElement, DC = window.DigitalCrew, I = DC.Icons;
  // Self-contained initials avatars (customer photos are remote in Crew OS).
  function avatar(name, bg) {
    var ini = name.split(" ").map(function (w) { return w[0]; }).join("");
    var svg = "<svg xmlns='http://www.w3.org/2000/svg' width='64' height='64'><rect width='64' height='64' fill='" + bg + "'/><text x='32' y='41' font-family='Arial' font-size='24' font-weight='600' fill='white' text-anchor='middle'>" + ini + "</text></svg>";
    return "data:image/svg+xml;utf8," + encodeURIComponent(svg);
  }
  function quote(a, hl, b) { return h("p", null, a, " ", h("span", { className: "font-semibold text-primary" }, hl), " ", b); }
  var testimonials = [
    { id: "1", name: "Claire Dubois", role: "CFO at Northwind Traders", img: avatar("Claire Dubois", "#8b5cf6"), description: quote("We handed our finance follow-ups to Max in March.", "Month-end chasing dropped from three days to one afternoon.", "Nobody wants the old way back.") },
    { id: "2", name: "Omar Haddad", role: "VP Finance at Brightline", img: avatar("Omar Haddad", "#0ea5e9"), description: quote("The first week felt like hiring a senior SDR.", "Eleven qualified meetings, zero manual lists.", "Our AEs finally sell all day.") },
    { id: "3", name: "Lena Fischer", role: "Head of Sales at Kestrel Labs", img: avatar("Lena Fischer", "#10b981"), description: quote("Replies are sorted by intent before I open my inbox.", "I only see the conversations worth my time.", "") },
    { id: "4", name: "Marc Lefèvre", role: "Founder at Atlas Freight", img: avatar("Marc Lefèvre", "#f59e0b"), description: quote("We run outbound in three languages with a team of two.", "Follow-ups never slip anymore.", "It just keeps going.") },
    { id: "5", name: "Aiko Tanaka", role: "COO at Vantage Health", img: avatar("Aiko Tanaka", "#ec4899"), description: quote("Sophie screens every applicant the same day.", "Time to first interview went from nine days to two.", "") },
    { id: "6", name: "Julien Moreau", role: "Revenue Ops at Helios Capital", img: avatar("Julien Moreau", "#6366f1"), description: quote("Everything lands in the CRM with the context attached.", "Our pipeline reviews take half the time.", "Clean data, finally.") }
  ];
  function App() { return h(DC.SocialProofTestimonials, { testimonials: testimonials }); }
  ReactDOM.createRoot(document.getElementById("root")).render(h(DC.TooltipProvider, { delayDuration: 80 }, h(App)));
})();
</script>