Retour au catalogue
Customer Stories Featured
Une histoire client featured : grande image, quote longue, resultats chiffres et auteur.
customer-storiesmedium Both Responsive a11y
elegantcorporatesaasuniversalsplit
Theme
"use client";
import { motion } from "framer-motion";
import { Quote, TrendingUp } from "lucide-react";
interface Metric {
label: string;
value: string;
}
interface CustomerStoriesFeaturedProps {
badge?: string;
companyName?: string;
companyLogo?: string;
quote?: string;
authorName?: string;
authorRole?: string;
imageSrc?: string;
metrics?: Metric[];
}
const ease: [number, number, number, number] = [0.16, 1, 0.3, 1];
export default function CustomerStoriesFeatured({
badge = "",
companyName = "",
companyLogo = "",
quote = "",
authorName = "",
authorRole = "",
imageSrc = "",
metrics = [],
}: CustomerStoriesFeaturedProps) {
return (
<section className="py-20 lg:py-28 px-6" style={{ background: "var(--color-background)" }}>
<div className="mx-auto max-w-5xl">
{badge && (
<motion.span
initial={{ opacity: 0 }}
whileInView={{ opacity: 1 }}
viewport={{ once: true }}
className="inline-block mb-8 px-3 py-1 text-xs font-medium tracking-wider uppercase rounded-full"
style={{ color: "var(--color-accent)", border: "1px solid var(--color-border)" }}
>
{badge}
</motion.span>
)}
<div className="grid grid-cols-1 lg:grid-cols-2 gap-12 items-center">
{/* Image */}
<motion.div
initial={{ opacity: 0, x: -24 }}
whileInView={{ opacity: 1, x: 0 }}
transition={{ duration: 0.6, ease }}
viewport={{ once: true }}
className="aspect-[4/3] rounded-2xl overflow-hidden flex items-center justify-center"
style={{
background: imageSrc ? undefined : "var(--color-background-alt)",
border: imageSrc ? undefined : "1px dashed var(--color-border)",
}}
>
{imageSrc ? (
<img src={imageSrc} alt={companyName} className="w-full h-full object-cover" />
) : (
<span className="text-sm" style={{ color: "var(--color-foreground-light)" }}>
Image client
</span>
)}
</motion.div>
{/* Content */}
<motion.div
initial={{ opacity: 0, x: 24 }}
whileInView={{ opacity: 1, x: 0 }}
transition={{ duration: 0.6, ease, delay: 0.1 }}
viewport={{ once: true }}
>
{companyLogo ? (
<img src={companyLogo} alt={companyName} className="h-8 mb-6 object-contain" />
) : companyName ? (
<span
className="inline-block mb-6 text-lg font-bold tracking-tight"
style={{ color: "var(--color-foreground)" }}
>
{companyName}
</span>
) : null}
<blockquote className="relative">
<Quote
size={32}
className="mb-4"
style={{ color: "var(--color-accent)", opacity: 0.3 }}
/>
<p
className="text-lg md:text-xl leading-relaxed"
style={{ color: "var(--color-foreground)", fontFamily: "var(--font-serif)", fontStyle: "italic" }}
>
{quote}
</p>
</blockquote>
{(authorName || authorRole) && (
<div className="mt-6">
{authorName && (
<p className="text-sm font-semibold" style={{ color: "var(--color-foreground)" }}>
{authorName}
</p>
)}
{authorRole && (
<p className="text-xs mt-0.5" style={{ color: "var(--color-foreground-muted)" }}>
{authorRole}
</p>
)}
</div>
)}
{metrics.length > 0 && (
<div
className="mt-8 pt-8 grid grid-cols-2 sm:grid-cols-3 gap-6"
style={{ borderTop: "1px solid var(--color-border)" }}
>
{metrics.map((metric, i) => (
<div key={i}>
<div className="flex items-center gap-1.5">
<TrendingUp size={14} style={{ color: "var(--color-accent)" }} />
<span
className="text-2xl font-bold"
style={{ color: "var(--color-accent)" }}
>
{metric.value}
</span>
</div>
<p className="mt-1 text-xs" style={{ color: "var(--color-foreground-muted)" }}>
{metric.label}
</p>
</div>
))}
</div>
)}
</motion.div>
</div>
</div>
</section>
);
}
Autres variantes customer-stories
Customer Stories Carousel
medium · both
elegantminimal
Customer Stories Grid
simple · both
minimalcorporate
Customer Stories Minimal
simple · both
minimalcorporate
Customer Stories Parallax
complex · both
boldelegant
Customer Stories Scroll
medium · both
elegantbold
Customer Story Before After
medium · both
boldplayful