---
title: Testimonials
description: Testimonial layouts for real customer voices.
group: Blocks
order: 43
---

A few ways to let customer words do the talking. Replace the quotes, names, and avatars with the real thing.

## Featured quote

One centered testimonial with an avatar and role.

```tsx
"use client";

import { cn } from "@/lib/utils";

type Testimonials01Props = {
  className?: string;
};

export function Testimonials01({ className }: Testimonials01Props) {
  return (
    <section className={cn("@container w-full bg-background", className)}>
      <div className="mx-auto flex w-full max-w-2xl flex-col items-center px-4 py-12 text-center @[32rem]:px-6 @[32rem]:py-16">
        <blockquote className="text-balance text-xl font-medium tracking-wide text-foreground @[32rem]:text-2xl">
          “We dropped in a hero and a navbar and shipped the marketing page the
          same afternoon. It already looked like us.”
        </blockquote>
        <div className="mt-8 flex flex-col items-center gap-3">
          <img
            src="/assets/brand/demos/avatars/avatar-1.png"
            alt=""
            className="size-10 rounded-full object-cover"
          />
          <div>
            <p className="text-sm font-medium tracking-wide text-foreground">
              Maya Chen
            </p>
            <p className="mt-0.5 text-xs tracking-wide text-muted-foreground">
              Head of Design, Northline
            </p>
          </div>
        </div>
      </div>
    </section>
  );
}
```

### Installation

```bash
npx @arctis-sh/@arctis-sh/ui@latest add testimonials-01
```

### Usage

```tsx
import { Testimonials01 } from "@/components/blocks/testimonials/testimonials-01"
```

```tsx
<Testimonials01 />
```

## Three up

Three concise quotes in a responsive grid.

```tsx
"use client";

import { cn } from "@/lib/utils";

type Testimonials02Props = {
  className?: string;
};

const TESTIMONIALS = [
  {
    quote: "Token-ready blocks — we stopped rebuilding the same sections every launch.",
    name: "Jordan Hale",
    role: "Founder, Relay",
    avatar: "/assets/brand/demos/avatars/avatar-2.png",
  },
  {
    quote: "CLI, drop-in, ship. Boring install story in the best way.",
    name: "Priya Nair",
    role: "Eng Manager, Cove",
    avatar: "/assets/brand/demos/avatars/avatar-3.png",
  },
  {
    quote: "Light and dark just worked. Time went to product, not palette fights.",
    name: "Chris Ortega",
    role: "Product, Stackwell",
    avatar: "/assets/brand/demos/avatars/avatar-4.png",
  },
] as const;

export function Testimonials02({ className }: Testimonials02Props) {
  return (
    <section className={cn("@container w-full bg-background", className)}>
      <div className="mx-auto w-full max-w-3xl px-4 py-8 @[32rem]:px-6 @[32rem]:py-12">
        <ul className="grid grid-cols-1 gap-3 @[40rem]:grid-cols-3">
          {TESTIMONIALS.map((item) => (
            <li
              key={item.name}
              className="flex flex-col rounded-xl bg-muted p-4"
            >
              <blockquote className="flex-1 text-xs tracking-wide text-foreground">
                “{item.quote}”
              </blockquote>
              <div className="mt-4 flex items-center gap-2.5">
                <img
                  src={item.avatar}
                  alt=""
                  className="size-7 shrink-0 rounded-full object-cover"
                />
                <div className="min-w-0">
                  <p className="truncate text-xs font-medium tracking-wide text-foreground">
                    {item.name}
                  </p>
                  <p className="truncate text-[11px] tracking-wide text-muted-foreground">
                    {item.role}
                  </p>
                </div>
              </div>
            </li>
          ))}
        </ul>
      </div>
    </section>
  );
}
```

### Installation

```bash
npx @arctis-sh/@arctis-sh/ui@latest add testimonials-02
```

### Usage

```tsx
import { Testimonials02 } from "@/components/blocks/testimonials/testimonials-02"
```

```tsx
<Testimonials02 />
```

## Marquee

An infinite ticker of compact review cards.

```tsx
"use client";

import { cn } from "@/lib/utils";

type Testimonials03Props = {
  className?: string;
};

const TESTIMONIALS = [
  {
    quote: "Shipped our launch site in a day.",
    name: "Maya Chen",
    role: "Northline",
    avatar: "/assets/brand/demos/avatars/avatar-1.png",
  },
  {
    quote: "Finally blocks that match our tokens.",
    name: "Jordan Hale",
    role: "Relay",
    avatar: "/assets/brand/demos/avatars/avatar-2.png",
  },
  {
    quote: "CLI install, drop in, done.",
    name: "Priya Nair",
    role: "Cove",
    avatar: "/assets/brand/demos/avatars/avatar-3.png",
  },
  {
    quote: "Dark mode without the cleanup pass.",
    name: "Chris Ortega",
    role: "Stackwell",
    avatar: "/assets/brand/demos/avatars/avatar-4.png",
  },
  {
    quote: "Looks custom without the custom bill.",
    name: "Sam Okonkwo",
    role: "Fieldkit",
    avatar: "/assets/brand/demos/avatars/avatar-5.png",
  },
] as const;

function QuoteCard({
  quote,
  name,
  role,
  avatar,
}: (typeof TESTIMONIALS)[number]) {
  return (
    <figure className="flex w-[18rem] shrink-0 flex-col justify-between rounded-xl border border-border bg-background p-5">
      <blockquote className="text-sm tracking-wide text-foreground">
        “{quote}”
      </blockquote>
      <figcaption className="mt-5 flex items-center gap-3">
        <img
          src={avatar}
          alt=""
          className="size-8 shrink-0 rounded-full object-cover"
        />
        <div className="min-w-0">
          <p className="truncate text-sm font-medium tracking-wide text-foreground">
            {name}
          </p>
          <p className="truncate text-xs tracking-wide text-muted-foreground">
            {role}
          </p>
        </div>
      </figcaption>
    </figure>
  );
}

export function Testimonials03({ className }: Testimonials03Props) {
  const track = [...TESTIMONIALS, ...TESTIMONIALS, ...TESTIMONIALS];

  return (
    <section className={cn("w-full overflow-hidden bg-background", className)}>
      <style>{`
        @keyframes testimonials-03-scroll {
          from { transform: translateX(0); }
          to { transform: translateX(-33.333%); }
        }
      `}</style>
      <div className="flex w-full flex-col gap-5 py-10">
        <p className="px-6 text-left text-xs tracking-wide text-muted-foreground">
          What teams say after they ship
        </p>
        <div className="w-full overflow-hidden" aria-hidden="true">
          <div
            className="flex w-max gap-3 pr-3"
            style={{ animation: "testimonials-03-scroll 40s linear infinite" }}
          >
            {track.map((item, i) => (
              <QuoteCard key={`${item.name}-${i}`} {...item} />
            ))}
          </div>
        </div>
      </div>
    </section>
  );
}
```

### Installation

```bash
npx @arctis-sh/@arctis-sh/ui@latest add testimonials-03
```

### Usage

```tsx
import { Testimonials03 } from "@/components/blocks/testimonials/testimonials-03"
```

```tsx
<Testimonials03 />
```
