shadcn.io is not affiliated with official shadcn/ui
Case Study Testimonial Block for Radix UI
A customer case study for a freight-tracking app, split by a hairline divider: the headline, a Shine Button and an at-a-glance list beside Challenge, Solution and Result bands with a headline figure and a pull quote.
Installation
Overview
Present one customer story in full with this case study testimonials block for React with Radix UI. The block splits in two with a hairline divider. The first column holds the story's headline, a Shine Button to the full write-up with a ghost link to more stories, and an "at a glance" list of the customer's industry, team size and time to launch. The second column is the narrative as bands ruled across it, with a + mark where each rule meets the divider: Challenge, Solution and Result, with the result's headline figure set large beside the words that explain it, then a pull quote and its speaker. On a phone the columns stack and the bands keep their rules. The speaker is an Avatar and every colour comes from your theme's tokens. The headline figure is worked out from the before and after numbers, so it can never disagree with the text. Made for landing pages, product marketing pages and customer story hubs where one transformative story is worth reading in full.
FAQ
How do I put my own customer's story in?
Edit the constants at the top of the file. COMPANY, DISPATCHERS and GLANCE fill the list and the intro, PLANNING and MISSED hold the before and after numbers, and the Challenge, Solution and Result paragraphs and the PERSON quote are plain text in the markup and the object beside them. The large figure is Math.floor(PLANNING.before / PLANNING.after), so changing the two numbers changes both the figure and the line beside it. Keep each claim something the customer has agreed to.
How is the story structured for screen readers?
The section's headline is an h2, and Challenge, Solution and Result are each an h3, so a screen reader can jump between them. The at-a-glance list is a description list, so each label is announced with its value. The quote is a figure with a blockquote and a caption naming the speaker, and the large figure and its caption sit together in one paragraph, so "18×" is read with "faster planning, from 6 hours to 20 minutes". The rules and + marks are decoration and hidden.
How do I load case studies from a CMS?
Replace the constants with props or a fetched object of the same shape: the list rows, the before and after numbers, the three paragraphs and the quote. The block is a server component with no state, so it can render a story fetched on the server with no client code, and the figure stays correct because it is computed from the numbers you pass.
How does it fit a phone, and a right-to-left page?
Below the lg breakpoint the two columns stack: the headline, the buttons and the list first, then the bands, each with its heading above its text and a full-width rule. It reads at 320px with no sideways scroll. In a right-to-left page the layout mirrors on its own, the divider and its + marks move to the other side, and the figure, the numbers and the quote each sit in a bdi, so "18×" and the quotation marks keep their order.
Does anything animate?
Only a single fade-up of the two columns when the page loads, in CSS, and it is off under reduced motion. The Shine Button sweeps its light across once when the pointer or keyboard focus arrives, and with reduced motion the light fades in where it stands. The headline figure is plain text from the first paint: it does not count up, so the page never shows a zero.