I did not fix anything in the first month. I just stopped pretending, which turned out to be the fix.
Ben Howard
One year
The room is the quietest place in my week. I would come just for that.
Esperanza Spalding
Eight months
Coaching gave me a plan. The plan gave me a reason to stop rewriting it.
Nick Mulvey
Ten sessions
Walking sessions. Say less, notice more. It works.
Arlo Parks
Fridays, on foot
Nobody rushed me toward a conclusion. I got there anyway, later, on my own feet.
Ólafur Arnalds
Two years
Online, from another country, and it still felt like being in the room.
Cat Power
Video sessions
A wall of six short testimonials on soft muted cards, the middle column set a step lower, each with a serif quote, a portrait, a name and a context line, under a serif heading that settles in word by word and a pill action.
A wall of short notes: six quotes on soft panels, each with an avatar and a context line, staggered so the middle column of every row sits a step lower.
Upgrade to Pro
Pro blocks install through the shadcn CLI with your license key and ship their full source. Docs and live previews stay open to everyone, so you can read every block's details first.
Swap YOUR_EMAIL and YOUR_KEY for the email and license key on your account. Find your license key on your account page.
Radix flavor
npx shadcn add "https://ui.beste.co/r/testimonial49?email=YOUR_EMAIL&license_key=YOUR_KEY"Base UI flavor
npx shadcn add "https://ui.beste.co/r-base/testimonial49?email=YOUR_EMAIL&license_key=YOUR_KEY"This installs the block to components/beste/block/testimonial49.tsx plus the button22 sliding-marker pill and the text1 word stagger it uses.
The installed file exports testimonial49Demo alongside the block: the exact props behind the preview above. Spread it to get a working testimonial wall in one line.
import { Testimonial49, testimonial49Demo } from "@/components/beste/block/testimonial49";
export default function Page() {
return <Testimonial49 {...testimonial49Demo} />;
}Then replace the demo with your own props. Written out, a trimmed setup looks like this:
import { Testimonial49 } from "@/components/beste/block/testimonial49";
export default function Page() {
return (
<Testimonial49
eyebrow="Said afterwards"
heading="Short notes, left on the way out."
button={{ label: "Leave your own", href: "/feedback", tone: "outline" }}
quotes={[
{
quote: "I did not fix anything in the first month. I just stopped pretending.",
name: "Ben Howard",
context: "One year",
avatar: { src: "/people/ben.jpg", alt: "Portrait" },
},
]}
/>
);
}| Prop | Type | Default | Description |
|---|---|---|---|
eyebrow | string | – | Small-caps line above the heading |
heading | string | – | Section heading, rendered as an h2 through Text1 |
button | ActionButton | – | Pill action beside the heading |
quotes | Quote[] | [] | Note cards, three across from md |
className | string | – | Extra classes for the outer <section> |
type Quote = {
quote: string;
name: string;
context: string;
avatar: { src: string; alt: string };
};
type ActionButton = {
label: string;
href: string;
tone?: "primary" | "light" | "dark" | "outline";
};lg:[&>*:nth-child(3n+2)]:mt-10, which drops the middle card of each row by a step; it applies to any number of quotes and disappears below lg where it would only look like broken spacing.(index % 3) * 0.12, so each row of three resolves left to right and the delay resets on the next row rather than growing across six cards.figure with a blockquote and a figcaption, so the attribution is bound to the words rather than merely following them.flex with justify-between, so every attribution sits at the foot of its panel and the avatars line up across a row of uneven quotes.bg-background circle inside the muted panel, so the empty ring reads as an inset rather than as a grey hole while the image loads.context is a free string, so "One year", "Ten sessions" or "Fridays, on foot" all read naturally.testimonial54
Three short testimonials in ruled columns, each a serif quote with a name and context, under a serif heading that settles in word by word and a sliding-marker pill.
testimonial36
A monochrome masonry wall of varying-height testimonial cards in a CSS columns layout.
testimonial32
Centered header above three vertically auto-scrolling columns of rated review cards with fade masks, pause-on-hover, and a closing CTA.