Skip to content
shadcn.io

shadcn.io is not affiliated with official shadcn/ui

Testimonial Grid Skeleton Block for React Aria

Three customer quote cells that load one after another: real quote marks and a heading over bars that become quotes, initials avatars, names and roles.

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

Show customer quotes while they load, then swap them in cell by cell, with this testimonial grid skeleton for React with React Aria. A hairline frame with a plus mark on each corner holds a band heading ("What teams say" and a count) over three quote cells on shared hairlines for Tuyere, a metal-fabrication marketplace, stacked on a phone. The frame, the heading and each cell's quote mark are real from the first paint; every three-line quote, initials Avatar, name and role is a Skeleton bar that becomes the content in the same box, a cell at a time from the start, when you press Load. Reload goes back to the bars. It's built from Skeleton, Avatar, Button and Guides, with a CSS entrance only. For testimonial sections whose quotes come from a CMS or a review service.

FAQ

What stays local, and how do I wire it to a real query?

Nothing is fetched. The three customers are typed in QUOTES, Load starts a 700 millisecond timer, and when it ends the phase becomes ready and the content swaps in; Reload goes back to the bars and in again. To wire it for real, delete the timer, the Load button and the polite line, and set data-state (loading or ready) and aria-busy on the region from your query's pending state, or use the bars as a Suspense fallback and render the real content when it arrives. The bars sit in the same cells as the content, so keep one component for both.

Why doesn't the grid jump when the quotes arrive?

Each bar and its content sit in one grid cell, so the larger of the two sets the cell's box and the swap changes nothing around it. Each cell has its quote bars, its avatar and its two lines of text in set boxes, and the cells keep one height on a row. The frame and the labels are real in both phases, and the polite line reserves two lines, so the panel is as tall before, during and after loading. A heading or a paragraph that wraps to more lines than its bars is the one thing that can still move the page, so give a text bar as many lines as the text takes at that width.

How many lines do the quote bars have?

The quotes are short enough to take three lines in a cell from the medium breakpoint and on a phone, and two lines when the cells are full width between them. The third bar is hidden for that range, so the bars match the text at each width. If you lengthen the quotes, add a bar.

What does the cell-by-cell reveal do?

Each cell's delay is its position times 120 milliseconds, so the cells fill from the start edge. Under reduced motion the delay is zero and the swap is instant.

Is it accessible?

The region is marked busy while it loads and carries a screen-reader-only "Loading quotes…", and the polite line says what loaded once. The bars are hidden from assistive technology and the layer that isn't showing is invisible, so it is neither read nor focusable. The pulse stops when the content is in, and under reduced motion there is no pulse, no spinner and no stagger: the swap is instant. Initials are decoration beside the name, and a quote is a blockquote.