shadcn.io is not affiliated with official shadcn/ui
Duo Testimonials Block for React
Two customer quotes from two different segments in one ruled band, split by a column that states the verdict they share as one big figure derived from both of their numbers, under a compact header with a Shine Button.
Installation
Overview
A testimonials section built on a comparison, for React with Base UI: two customers from two unlike segments, one result. A compact header and one Shine Button sit above a single ruled band whose rules end at the page rails, with + marks on its corners. In the band, each customer gets a cell with a segment label, a five-star rating, the quote, the author and their own figure. Between the cells a column states the line they agree on, such as "Both cut review time by 40%", with the number set large. On wide screens that column is a vertical strip between the cells; on a phone the cells stack and it becomes a row between them. The fictional product is Parapet, a review queue. It's built from Badge, Avatar, Guides and Shine Button, with Lucide's star icon, CSS transitions only and your theme's tokens. For pages where you sell to more than one kind of buyer and want to show the result isn't a fluke.
FAQ
Where does the figure in the middle column come from?
It's worked out from the two cells, not typed by hand. Each voice has a cut figure, and the verdict takes the smaller one: if both are 40 it reads "Both cut review time by" 40%, and if they differ it reads "Both cut review time by at least" the lower figure. Change the numbers in VOICES and the verdict follows, so the claim can never overstate what the cells show.
How do I change the two voices?
Edit COMPLIANCE and DESIGN at the top of the file: segment label, name, role, company, quote, rating, initials and cut. Pick two customers whose situations really differ, and use figures they've agreed to share.
How do screen readers read it?
The heading is the section's h2. Each cell is a figure with a blockquote, a figcaption for the author and a short definition list for the figure. The stars are decorative, and a hidden line says "Rated 5 out of 5". The verdict is real text read between the two cells.
How does it fit a phone?
Below the lg breakpoint the cells stack with the verdict between them as a row with hairlines above and below. The reading order is the same at every width. At 320px nothing scrolls sideways, and the first quote starts inside the first screen.
Does it work in right-to-left languages?
Yes. The cells swap sides and the verdict stays centred between them. Quotes sit in a bdi so their marks stay at the ends of the sentence, and the percentages are wrapped so the minus sign stays in front of the number.
Related
- Pro
Two Column Testimonials
Rows and listsA testimonials section split by a solid divider: a pinned intro column with the heading and a Shine Button beside five customer quotes set as ruled rows, the first one larger.
- Pro
Three Column Testimonials
Quote gridsThree customer quotes with no card chrome: a centred header over one closing band of three columns, each a large initials avatar over a centred quote, divided by hairlines.
- Pro
Mini Cards Testimonials
Quote gridsEight square tiles in a hairline grid, each holding a one-line customer quote at the top and its author at the foot, with the one Shine Button in the header row.
- Pro
Kanban Testimonials
Walls and lanesCustomer quotes sorted into three theme lanes with a count on each header, in one ruled band: a board of tinted lanes with raised cards on desktop, swipeable lanes in a named scroll area on a phone.
- Pro
Split Layout Testimonial Card Hero
TestimonialsA split hero for month-end close software: the pitch, a Shine Button and an outline button beside a customer's five-star testimonial in a card in a card, with the two results it names.
- Pro
Animated Count Testimonials
Results and figuresThree headline figures that count up to their totals when the section loads, in one hairline band with a Replay button that runs the count again, and two customer quotes in a second band beneath.