Skip to content

Components / Sections

Testimonial Cards

Shows testimonial quotes in a staggered grid. Each card tilts gently toward the cursor, and the featured quote spans two columns with its words revealed one by one. Attribution with avatar and role.

Live demo

Every byte on the page is accounted for, and the number is on the page.

A. DeveloperAstro user

Replaced three React islands with zero.

B. BuilderAgency

The preset switcher sold it.

C. Designer

Live, from the library itself, at full size: scroll, hover, navigate away and back. The demo is never gated.

Variants · each row writes the attribute the prop writes; the section's own CSS answers

tone
density
columns

Measured

JavaScript of its own

0 B

Uses Tilt and the shared runtime (1.9 kB raw, once per site) and Reveal. With those included: 3.5 kB raw.

CSS 12.4 kB raw including the base tokens. Measured from a production build, and again in CI for every change that can move it.

Browser support

Baseline · widely available

every browser.

Install Pro

The demo above is never gated; the source is. With a key in components.json (see account), the registry serves it like any other item:

terminal
npx shadcn@latest add @moonarc-pro/testimonial-cards
src/pages/index.astro
---
import TestimonialCards from '@/components/moonarc/pro/TestimonialCards.astro';
---
<TestimonialCards quotes={[
  { quote: 'Every byte on the page is accounted for.', name: 'A. Developer', role: 'Astro user', featured: true },
  { quote: 'Replaced three React islands with zero.', name: 'B. Builder' },
]} />

Without a key the registry answers 401 with an upgrade message. Everything this section composes is free: reveal, tilt, split-text.

Props

PropTypeDefaultDescription
quotes{ quote, name, role?, avatar?, featured? }[]noneQuotes; a featured one spans two columns and splits its text.
columns2 | 3 | 43Columns on wide screens.
tone'surface' | 'muted' | 'ink' | 'brand'unset (paints nothing)The ground: the page surface, a muted band, an always-dark ink panel, or a deep brand panel. Each paints --background, --ma-tone-muted (over --muted, with a --border hairline), --ma-tone-ink or --ma-tone-brand (over --primary) with the matching text. With theme.css, a painted tone also re-declares --card, --border, --input and --ring inside the section, so cards and fields follow the ground. Decoration is strongest on brand.
density'compact' | 'cozy' | 'roomy''cozy'Card padding and gaps ×0.8 / ×1 / ×1.25 through --ma-density.

Theming and overrides

The section reads the theme contract (shadcn's variable names with the base tokens as fallback), so a pasted theme or one --ma-brand recolours it. Its class names are the override surface and stay stable; a named slot replaces the matching prop with your own markup.

Classes

.ma-testimonials.ma-testimonials__card.ma-testimonials__copy.ma-testimonials__eyebrow.ma-testimonials__head.ma-testimonials__headline.ma-testimonials__quote.ma-testimonials__who

Slots

slot="eyebrow"slot="headline"slot="copy"

Reduced motion

Cards fade in without stagger; no tilt; the featured quote appears at once.

With ClientRouter

Inherits Reveal, Tilt and SplitText; nothing to wire.

Why it is built this way

Replaces: Testimonial sections (Tailwind Plus) · AnimatedTestimonials (Aceternity). See the migration table.

Entrance on scroll that plays once and stays, staggers its children, scrubs with the scroll position when asked, honours reduced motion, and keeps working after every ClientRouter navigation.

every browserscroll

Splits a string into words, characters or lines on the server and reveals them with a capped stagger when they scroll into view.

every browserscroll

Tilt

Pointer

A card leans toward the cursor in 3D, lifts slightly, catches a glare, and settles back on the active preset's spring when the cursor leaves.

every browserpointerhover

Shows two rows of testimonial cards drifting in opposite directions, pausing while hovered so any quote can be read.

every browseralwayshover

Also: view transitions · how costs are measured · browser support · accessibility policy · five-minute setup · MCP for agents · this page as Markdown