
An interactive client testimonials block featuring tabbed categorization (e.g., startups vs enterprise), custom metrics display, and trust rating social proof in the footer.
components/blocks/marketing/testimonials/testimonials-1.tsx
import { useState } from "react";
import { ArrowUpRight, MessageSquareIcon, QuoteIcon, StarIcon } from "lucide-react";
import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar";
import { Badge } from "@/components/ui/badge";
import { Button } from "@/components/ui/button";
import { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle } from "@/components/ui/card";
import { Tabs, TabsList, TabsTrigger } from "@/components/ui/tabs";
const categoriesData: Record<
string,
Array<{
quote: string;
author: string;
role: string;
initials: string;
metric?: string;
metricLabel?: string;
}>
> = {
startups: [
{
quote: "PaceUI allowed us to launch our MVP in days rather than months. The customizability of the templates is top-notch.",
author: "Aria Chen",
role: "Co-Founder, SparkAI",
initials: "AC",
metric: "10X",
metricLabel: "Faster build speed",
},
{
quote: "We've tried multiple UI kits, but this one is by far the cleanest and most performance-focused.",
author: "Jared Finch",
role: "CTO, NextFlow",
initials: "JF",
},
{
quote: "Excellent developer experience. The components slot perfectly into our existing design system without styling overrides.",
author: "Maya Lin",
role: "Lead Designer, Loom",
initials: "ML",
},
],
enterprise: [
{
quote: "Standardizing our internal dashboards around these templates saved us hundreds of engineering hours this quarter alone.",
author: "Robert Kowalski",
role: "Director of Engineering, Salesforce",
initials: "RK",
metric: "40%",
metricLabel: "Reduction in dev cost",
},
{
quote: "The adherence to accessibility and clean markup is fantastic. It passed our strict internal audit with ease.",
author: "Sarah Jenkins",
role: "VP Accessibility, IBM",
initials: "SJ",
},
{
quote: "A comprehensive library that allows our design and dev teams to speak the exact same language day in and day out.",
author: "Tatsuya Hiro",
role: "Design Lead, Sony",
initials: "TH",
},
],
};
export const Testimonials1 = () => {
const [activeTab, setActiveTab] = useState<string>("startups");
const currentTestimonials = categoriesData[activeTab] || [];
const featured = currentTestimonials[0];
const rest = currentTestimonials.slice(1);
return (
<div className="container py-12">
<div className="flex flex-col items-center justify-center text-center">
<Badge variant="outline">Use Cases</Badge>
<h2 className="mt-2 text-3xl font-semibold tracking-tight md:text-4xl">Proven impact at any scale</h2>
<Tabs value={activeTab} onValueChange={setActiveTab} className="mt-4">
<TabsList>
<TabsTrigger value="startups" className="cursor-pointer rounded-md">
Startups
</TabsTrigger>
<TabsTrigger value="enterprise" className="cursor-pointer rounded-md">
Enterprise
</TabsTrigger>
</TabsList>
</Tabs>
</div>
<div className="mt-8 grid grid-cols-1 gap-6 md:grid-cols-12">
{featured && (
<Card className="md:col-span-7">
{featured.metric ? (
<CardHeader>
<CardTitle className="text-4xl font-semibold tracking-tight">
{featured.metric}
</CardTitle>
<CardDescription className="text-sm font-medium">
{featured.metricLabel}
</CardDescription>
</CardHeader>
) : null}
<CardContent className="grow">
<QuoteIcon className="text-foreground/20 size-8 -rotate-180"></QuoteIcon>
<p className="mt-2 text-base leading-relaxed">{featured.quote}</p>
</CardContent>
<CardFooter className="flex items-center gap-3 border-t border-dashed">
<Avatar>
<AvatarImage src="" />
<AvatarFallback>{featured.initials}</AvatarFallback>
</Avatar>
<div className="flex flex-col">
<span className="text-sm font-medium">{featured.author}</span>
<span className="text-muted-foreground text-[11px]">{featured.role}</span>
</div>
</CardFooter>
</Card>
)}
<div className="flex flex-col gap-6 md:col-span-5">
{rest.map((item, index) => (
<Card key={index}>
<CardContent>
<QuoteIcon className="text-foreground/15 size-6 -rotate-180"></QuoteIcon>
<p className="mt-2 text-base leading-relaxed">{featured.quote}</p>
</CardContent>
<CardFooter className="flex items-center gap-3 border-t border-dashed">
<Avatar>
<AvatarImage src="" />
<AvatarFallback>{item.initials}</AvatarFallback>
</Avatar>
<div className="flex flex-col">
<span className="text-sm font-medium">{item.author}</span>
<span className="text-muted-foreground text-[11px]">{item.role}</span>
</div>
</CardFooter>
</Card>
))}
</div>
</div>
<div className="mt-6 flex flex-col items-center justify-between gap-4 sm:flex-row">
<div className="flex flex-wrap items-center gap-4">
<div className="bg-muted flex size-8 items-center justify-center rounded-md border select-none">
<MessageSquareIcon className="size-3.5" />
</div>
<div className="flex flex-col">
<div className="flex items-center gap-0.5">
{[...Array(5)].map((_, i) => (
<StarIcon key={i} className="size-4 fill-orange-400 text-orange-400" />
))}
<span className="ms-2 text-sm font-medium">4.9</span>
</div>
<span className="text-muted-foreground text-xs">Based on 1.5k reviews</span>
</div>
</div>
<span className="text-sm">1500 satisfied clients love our services</span>
<Button variant="outline" size="sm">
View all reviews
<ArrowUpRight className="size-3" />
</Button>
</div>
</div>
);
};