Skip to content
shadcn.io

shadcn.io is not affiliated with official shadcn/ui

Pin a Quote Testimonials Block for React

Four quote rows in a ruled list with Pin toggles: the pinned quote moves up into a large featured card, a raised panel in a tinted shell with + marks, split from the list by a solid divider, under a compact header with a Shine Button.

Framework
UI library

Preview

Preview width

Installation

Part of Pro
Pro unlocks the code and one-line install of every Pro button and text effect, plus the MCP for your AI editor.
Have Pro already? Sign in to open it.Opens here as soon as you're Pro.

Overview

A testimonials section where the visitor, or you, picks the featured quote, for React with Base UI. A compact header names the section and carries one Shine Button. Below it the page column splits at lg with a solid divider: on one side the featured stage, a raised card inside a tinted shell with + marks on its corners; on the other four short quotes in a ruled list, each with a Pin toggle. The pinned one is shown large in the stage under a "Pinned" badge; pinning another quote swaps them, and unpinning shows a calm empty slot. The first quote is pinned on load, so the section opens complete, and on a phone the stage comes first with the list below. One piece of state drives everything: the pinned id. The stage holds every card in one grid cell, so it's as tall as the tallest and nothing around it moves. The fictional product is Plover, a team workspace. It's built from Toggle, Badge, Avatar, Guides and Shine Button, with CSS transitions only and your theme's tokens; the lit toggle is in the text colour, never the primary. For landing pages with a few strong quotes where you'd like to preview which one leads.

FAQ

How does pinning work?

The component keeps one pinned id. Each row's toggle is pressed when its id is the pinned one; pressing it sets the id, and pressing the pinned one again clears it. The stage shows the card whose id matches, or the empty slot when nothing is pinned. To pin more than one quote, keep a list of ids and render a card for each.

Why doesn't the page jump when I pin another quote?

Every featured card, and the empty slot, is stacked in one grid cell, so the stage always takes the height of the tallest. The cards that aren't pinned are invisible and inert, and the new one fades in with an opacity transition. Quotes of very different lengths just make the stage as tall as the longest one.

How do keyboards and screen readers use it?

Each Pin is a real toggle button reading "Pin Bao Tran's quote, toggle button, pressed" when it's lit. Tab moves through the four; Space and Enter pin and unpin. The cards that aren't showing are hidden from assistive technology and can't take focus. A polite status line announces "Pinned Lena Albrecht's quote as the featured one" after each press, and says nothing on load.

What are the Pinned badge and the shell around the card?

The badge is an outline Badge with a pin icon, decoration for the state the toggle already announces. The shell is a tinted box with a hairline border and + marks on its corners, holding a raised bg-card panel with a soft shadow and a ring: emphasis comes from that structure, and no part of the card is filled with the primary colour.

Does the pin persist or change the real page?

No. It's local state in the preview, so a reload goes back to the first quote. To keep a choice, send it to your CMS or settings from pin, or read the pinned id from your data instead of state and drop the toggles.

How does it fit on a phone?

Below lg the divider becomes a rule: the stage first, then the list. The featured quote's type steps down to text-xl, and in the list each Pin sits at the end of the author line. Nothing has a fixed width or height, and the block fits within about two and a half screens at 375 px.

How is the Shine Button built on each library?

The header's button is the block's only primary control, a link to your customer wall. On Base UI, the button renders its link with render={<a href="#" />} and nativeButton={false}.

  • Pro

    A quote-only bento drawn with hairlines: one large lead story beside four shorter quotes, in cells that share their lines, on the page's drafting lines.

  • Pro

    Flip Card Testimonials

    Expand, flip, pin

    Three testimonial cells in one hairline band that flip in 3D from a short quote to the results behind it, one open at a time, each driven by a toggle button.

  • Pro

    Three long stories from Fieldnote's customers in elastic columns inside one framed figure: the story you hover or focus widens while the others give way, and each clamped quote opens in full.

  • Pro

    A checkerboard of monogram portrait tiles and quote tiles in cells that share their hairlines, each quote beside its speaker and the second row swapped, under a compact header with a Shine Button.

  • Pro

    A reverse split hero with a card that shows one customer quote at a time in a hairline frame, a pause button and a dot per quote, beside an announcement pill, a headline, a Shine Button and an outline action.

  • Pro

    A split hero for a release management tool: copy and two calls to action beside one customer quote in a raised card in a card, with the customer's name, role and a before and after of their result.