All componentsdisplay
Testimonial Card
“We swapped our whole component layer over a weekend. The token discipline made theming trivial.”
Priya ShahHead of Design, Northwind
“The accessibility work alone would have taken us a month to get right on our own.”
Marcus WebbEngineering Lead
Installation
$ npx shadcn@latest add https://deepmoon.dev/r/testimonial-card.jsonProps
TestimonialCardProps
| Prop | Type | Required |
|---|---|---|
| quote | string | Yes |
| author | string | Yes |
| role | string | No |
| company | string | No |
| avatarSrc | string | No |
Code
testimonial-card.tsx
import * as React from "react";
import { cn } from "@/lib/utils";
export interface TestimonialCardProps extends React.ComponentPropsWithoutRef<"figure"> {
quote: string;
author: string;
role?: string;
company?: string;
avatarSrc?: string;
}
export function TestimonialCard({
quote,
author,
role,
company,
avatarSrc,
className,
...props
}: TestimonialCardProps) {
return (
<figure
className={cn("flex flex-col gap-4 rounded-lg border border-border bg-card p-6 text-card-foreground", className)}
{...props}
>
<blockquote className="text-sm leading-relaxed text-foreground">“{quote}”</blockquote>
<figcaption className="flex items-center gap-3">
{avatarSrc ? (
<img src={avatarSrc} alt="" className="size-9 shrink-0 rounded-full object-cover" />
) : (
<span
aria-hidden="true"
className="flex size-9 shrink-0 items-center justify-center rounded-full bg-muted text-xs font-medium text-muted-foreground"
>
{author.slice(0, 1).toUpperCase()}
</span>
)}
<div className="flex flex-col">
<span className="text-sm font-medium text-foreground">{author}</span>
{role || company ? (
<span className="text-xs text-muted-foreground">
{role}
{role && company ? ", " : ""}
{company}
</span>
) : null}
</div>
</figcaption>
</figure>
);
}