Case study 01
Northstar
We replaced three hand-offs with one visible decision trail. The team now knows why a release moved.
A free testimonial selector that keeps every company visible while one case study and outcome takes focus.
Customer evidence
Select a company to see the result behind the quote.
Case study 01
We replaced three hand-offs with one visible decision trail. The team now knows why a release moved.
Case study 02
Evidence sits beside the work instead of disappearing into another dashboard. Reviews are shorter and better.
Case study 03
Every launch starts with the same definition of success, so product and go-to-market move together.
<QuoteCaseStudySelector
title="Proof from teams that ship"
description="Select a company to see the result behind the quote."
items={[
{
id: "northstar",
company: "Northstar",
quote: "We replaced three hand-offs with one visible decision trail. The team now knows why a release moved.",
author: "Maya Chen",
role: "VP Product",
result: "3.4x",
resultLabel: "faster release cycles",
},
{
id: "arc",
company: "Arc Systems",
quote: "Evidence sits beside the work instead of disappearing into another dashboard. Reviews are shorter and better.",
author: "Theo Martin",
role: "Engineering Director",
result: "41%",
resultLabel: "less review time",
},
{
id: "fieldnote",
company: "Fieldnote",
quote: "Every launch starts with the same definition of success, so product and go-to-market move together.",
author: "Priya Shah",
role: "Chief Operating Officer",
result: "18 days",
resultLabel: "saved per launch",
},
]}
/>Case Study Selector is a free testimonial component for Next.js and React that presents customer evidence as manual company tabs with no autoplay. Built with Motion and styled with Tailwind, it pairs each quote with a visible outcome metric so visitors can move directly to the proof that matters to them.
The selector becomes a vertical master-detail layout on desktop and a touch-scrollable horizontal tab list on mobile. Every case study is rendered once in a shared intrinsic grid cell, so the tallest story reserves the panel height, while JavaScript-free pages restore the same articles as a readable stacked list with fragment links.
Add the @te registry to your components.json once:
{
"registries": {
"@te": "https://templateempire.io/r/{name}.json"
}
}Then install the component:
npx shadcn@latest add @te/quote-case-study-selectorimport {
QuoteCaseStudySelector,
type CaseStudyItem,
} from "@/components/quote-case-study-selector";
const caseStudies: CaseStudyItem[] = [
{
id: "northstar",
company: "Northstar",
quote:
"We replaced three hand-offs with one visible decision trail. The team now knows why a release moved.",
author: "Maya Chen",
role: "VP Product",
result: "3.4x",
resultLabel: "faster release cycles",
},
{
id: "arc",
company: "Arc Systems",
quote:
"Evidence sits beside the work instead of disappearing into another dashboard. Reviews are shorter and better.",
author: "Theo Martin",
role: "Engineering Director",
result: "41%",
resultLabel: "less review time",
},
];
export function CustomerProof() {
return (
<QuoteCaseStudySelector
title="Proof from teams that ship"
description="Select a company to see the result behind the quote."
items={caseStudies}
/>
);
}| Prop | Type | Default | Description |
|---|---|---|---|
| title | string | required | Section heading rendered as an h2. |
| description | string | undefined | Optional section introduction. |
| items | CaseStudyItem[] | required | Two to six case studies with a stable ID, company, quote, author, optional role and logo, result, and result label. |
| value | string | undefined | Controlled active item ID. |
| defaultValue | string | first item ID | Initial item ID for uncontrolled use. Invalid IDs fall back to the first case study. |
| onValueChange | (id: string) => void | undefined | Called once after pointer or keyboard selection changes the active item. |
| panelOffset | number | 24 | Directional panel travel in pixels, clamped from 0 to 48 and ignored under reduced motion. |
| className | string | undefined | Additional classes merged onto the section root. |
Case Study Selector exposes four Tier 3 colour tokens. Override --case-study-tab for inactive selector surfaces, --case-study-active for the shared active indicator, --case-study-panel for the quote surface and --case-study-border for the section rules. The panelOffset prop controls real transition geometry from 0 to 48 pixels, while all wording and case-study data stay in your items array.
.customer-proof {
--case-study-tab: var(--surface);
--case-study-active: var(--primary);
--case-study-panel: var(--background);
--case-study-border: var(--border);
}
<QuoteCaseStudySelector
className="customer-proof"
title="Proof from teams that ship"
items={caseStudies}
panelOffset={32}
/>