Skip to content
Facade UI
blockmotion

Testimonials grid (motion)

The testimonials grid, with quotes appearing one after another as you scroll to it.

Open in v0 (opens in a new tab)

This is the animated version of Testimonials grid. The static version looks the same with JavaScript turned off.

Preview

Open full width (opens in a new tab)
Preview width

Installation

Package manager
pnpm dlx shadcn@latest add https://facadeui.dev/r/testimonials-grid-motion.json

This component needs motion-primitives, testimonials-grid. The CLI installs them for you.

Usage

This is the code for the preview above. To install it as a file, run npx shadcn@latest add @facade/testimonials-grid-motion-demo.

demos/testimonials-grid-motion.tsx
"use client"

/**
 * The `testimonials-grid` demo, with the motion variant swapped in.
 *
 * Identical props: the motion variant only changes which slot components
 * the static section renders through.
 *
 * `"use client"` is required here, not incidental: the motion variant is a
 * client component, and icon components cannot cross a server-to-client
 * boundary as props. See the note on `IconComponent`.
 */

import { TestimonialsGridMotion } from "@registry/sections/testimonials-grid-motion"

import { QUOTES } from "./content"

export function Demo() {
  return (
    <TestimonialsGridMotion
      eyebrow="Customers"
      title="What teams say"
      description="Masonry columns flow in document order, so reading order still matches what you see."
      items={QUOTES}
      columns="masonry"
    />
  )
}

Source

These are the files the CLI copies into your project.

components/sections/testimonials-grid-motion.tsx
"use client"

/**
 * TestimonialsGridMotion — the testimonial wall with a staggered entrance.
 *
 * Quotes arrive one after another as the wall scrolls in.
 *
 * A genuine wrapper: it renders the static `TestimonialsGrid` and only swaps the list
 * slots, so no markup, styling or accessibility behaviour is duplicated. *
 * Dependencies: react, @/components/motion/slots,
 * @/components/sections/testimonials-grid.
 */

import { StaggerList, StaggerListItem } from "@/components/motion/slots"
import {
  TestimonialsGrid,
  type TestimonialsGridProps,
} from "@/components/sections/testimonials-grid"

export type TestimonialsGridMotionProps = Omit<TestimonialsGridProps, "listAs" | "itemAs">

export function TestimonialsGridMotion(props: TestimonialsGridMotionProps) {
  return <TestimonialsGrid {...props} listAs={StaggerList} itemAs={StaggerListItem} />
}

Props

TestimonialsGridMotionProps

Extends Omit<TestimonialsGridProps, "listAs" | "itemAs">.