All Taste components
Testimonials
Testimonial — quote beside a portrait
One customer’s quote set beside a tall portrait, with two results from their story and a link to read it.
portrait with name tag · large quote · 2 result figures · company mark · stacks on small screens
Nadia FerreiraOwner, Saltmarsh Bakery
Customer since 2023“Saturday pre-orders used to arrive by text, email and phone. Now customers pick a pickup slot themselves, and I bake for exactly the orders I have.”
- Orders taken online
- 9 in 10
- Admin saved each week
- 6 hrs
import { ArrowRight } from "lucide-react";
const story = {
quote: "Saturday pre-orders used to arrive by text, email and phone. Now customers pick a pickup slot themselves, and I bake for exactly the orders I have.",
name: "Nadia Ferreira",
role: "Owner, Saltmarsh Bakery",
since: "Customer since 2023",
company: "Saltmarsh",
stats: [
{ label: "Orders taken online", value: "9 in 10" },
{ label: "Admin saved each week", value: "6 hrs" },
],
href: "/customers/saltmarsh",
};
export function TestimonialPortrait() {
return (
<section aria-label="Customer story" className="bg-bg px-5 py-12 font-sans sm:px-10 sm:py-20">
<div className="mx-auto grid max-w-6xl items-center gap-9 md:grid-cols-[0.85fr_1.15fr] md:gap-16">
{/* Swap the gradient for <img src="..." alt="Portrait of Nadia Ferreira" className="size-full object-cover" /> */}
<div role="img" aria-label={"Portrait of " + story.name}
className="relative aspect-[4/5] max-h-[520px] w-full overflow-hidden rounded-xl bg-gradient-to-br from-brand-300 via-brand-600 to-brand-900 shadow-2xl">
<div className="absolute inset-x-4 bottom-4 flex flex-wrap items-center justify-between gap-2 rounded-lg bg-neutral-950/60 px-3.5 py-2.5 text-[13px] text-neutral-50 backdrop-blur">
<div>
<p className="text-sm font-semibold">{story.name}</p>
<p className="text-neutral-50/75">{story.role}</p>
</div>
<span className="text-neutral-50/75">{story.since}</span>
</div>
</div>
<figure className="grid justify-items-start gap-6">
<svg viewBox="0 0 40 40" className="size-[38px] text-primary" fill="currentColor" aria-hidden>
<path d="M6 30V20.5C6 13.6 9.6 9.4 16.4 8l1.2 3.4c-3.6 1.1-5.4 3.4-5.6 6.6H17V30H6Zm17 0V20.5c0-6.9 3.6-11.1 10.4-12.5l1.2 3.4c-3.6 1.1-5.4 3.4-5.6 6.6H34V30H23Z" />
</svg>
<blockquote className="text-pretty text-[22px] font-medium leading-snug tracking-tight text-fg sm:text-3xl">
<p>“{story.quote}”</p>
</blockquote>
<dl className="grid w-full grid-cols-2 gap-3">
{story.stats.map((s) => (
<div key={s.label} className="rounded-lg bg-surface px-4 py-3.5">
<dt className="text-[13px] text-fg-muted">{s.label}</dt>
<dd className="mt-1 text-[26px] font-semibold tabular-nums tracking-tight text-fg">{s.value}</dd>
</div>
))}
</dl>
<figcaption className="flex w-full flex-wrap items-center gap-x-6 gap-y-3 border-t border-border pt-5">
<span className="font-serif text-lg font-semibold italic text-fg">{story.company}</span>
<a href={story.href} className="ml-auto inline-flex items-center gap-1.5 text-sm font-medium text-primary hover:underline">
Read Nadia’s story <ArrowRight className="size-4" aria-hidden />
</a>
</figcaption>
</figure>
</div>
</section>
);
}
The code uses the Taste Tailwind preset. Make yours on the Taste page with Export my system.