# Testimonials 11

> A simple testimonials block

A shadcn/ui block from the [@shadcnui-blocks](https://shadcnui-blocks.com) registry, listed on [shadcn.exchange](https://shadcn.exchange/r/shadcnui-blocks/testimonials-11).

- Page, with a live preview: https://shadcn.exchange/r/shadcnui-blocks/testimonials-11
- Screenshot: https://abzjhwgwpdpz7ua5.public.blob.vercel-storage.com/shots/shadcnui-blocks/testimonials-11-light-3538ed682778b415.png
- Registry item: https://shadcnui-blocks.com/r/testimonials-11.json
- Listed: 2026-10-13, source last changed 2026-10-13

## Install

```bash
npx shadcn@latest add https://shadcnui-blocks.com/r/testimonials-11.json
```

Run it in a project that has shadcn/ui set up. It adds the files below and installs what they depend on.

## Files

### `src/registry/blocks/radix/testimonials-11/components/testimonials.tsx`

```tsx
"use client";

import React from "react";
import { cn } from "@/lib/utils";
import {
  Carousel,
  type CarouselApi,
  CarouselContent,
  CarouselItem,
  CarouselNext,
  CarouselPrevious,
} from "@/registry/bases/radix/ui/carousel";

const testimonials = [
  {
    name: "Sarah Johnson",
    role: "Product Designer at Canva",
    avatar: "https://mockmind-api.uifaces.co/content/human/97.jpg",
    testimonial:
      "This product completely changed the way I work. The interface is intuitive and the performance is top-notch.",
  },
  {
    name: "Raj Mehta",
    role: "Frontend Developer at Zomato",
    avatar: "https://mockmind-api.uifaces.co/content/human/80.jpg",
    testimonial:
      "It's rare to find a tool that blends design and usability so well. Highly recommend it to all developers!",
  },
  {
    name: "Emily Chen",
    role: "Marketing Manager at HubSpot",
    avatar: "https://mockmind-api.uifaces.co/content/human/113.jpg",
    testimonial:
      "The experience has been seamless from day one. Great support, fast delivery, and amazing value.",
  },
  {
    name: "Daniel Kim",
    role: "CTO at NextLaunch",
    avatar: "https://mockmind-api.uifaces.co/content/human/90.jpg",
    testimonial:
      "We integrated this solution into our workflow and saw an instant boost in productivity and collaboration.",
  },
  {
    name: "Aisha Patel",
    role: "Software Engineer at Swiggy",
    avatar: "https://mockmind-api.uifaces.co/content/human/116.jpg",
    testimonial:
      "I've used several tools in this category, but nothing matches the polish and reliability of this one.",
  },
  {
    name: "Liam Garcia",
    role: "Startup Founder",
    avatar: "https://mockmind-api.uifaces.co/content/human/112.jpg",
    testimonial:
      "As a founder, I care about speed and simplicity. This product delivers on both fronts beautifully.",
  },
];

const Testimonials = () => {
  const [api, setApi] = React.useState<CarouselApi | null>(null);
  const [count, setCount] = React.useState(0);
  const [current, setCurrent] = React.useState(0);

  React.useEffect(() => {
    if (!api) {
      return;
    }

    setCount(api.scrollSnapList().length);
    setCurrent(api.selectedScrollSnap() + 1);

    api.on("select", () => {
      setCurrent(api.selectedScrollSnap() + 1);
    });
  }, [api]);

  return (
    <div className="mx-auto max-w-7xl px-6 py-12 sm:py-20">
      <h2 className="text-center font-medium text-4xl tracking-tight md:text-4xl">
        What others think
      </h2>
      <p className="mt-2 text-balance text-center text-lg text-muted-foreground sm:mt-4 sm:text-2xl">
        Real stories from real users with real results
      </p>

      <div className="mx-auto mt-20 max-w-248 md:mt-16 md:px-12">
        <Carousel
          opts={{
            align: "start",
          }}
          setApi={setApi}
        >
          <CarouselContent>
            {testimonials.map(({ name, avatar, role, testimonial }, index) => (
              <CarouselItem key={index}>
                <div className="relative flex gap-8 rounded-lg border bg-muted/70 p-8 pt-16 pr-8 md:pt-8">
                  {/* Quote */}
                  <span className="absolute top-3 left-6.5 font-satoshi text-8xl md:hidden">
                    &ldquo;
                  </span>

                  <div className="flex flex-col gap-2">
                    <p className="grow font-medium text-xl leading-relaxed tracking-tight sm:text-2xl sm:leading-[1.45] lg:text-3xl">
                      {testimonial}
                    </p>
                    <div className="mt-6 flex items-center gap-2 md:mt-0">
                      <img
                        alt=""
                        className="aspect-square h-12 rounded-full md:hidden"
                        src={avatar}
                      />
                      <div className="flex flex-col">
                        <p className="font-medium text-lg">{name}</p>
                        <p className="text-muted-foreground">{role}</p>
                      </div>
                    </div>
                  </div>
                  <img
                    alt=""
                    className="hidden aspect-square max-w-60 rounded-lg md:block"
                    src={avatar}
                  />
                </div>
              </CarouselItem>
            ))}
          </CarouselContent>

          <CarouselPrevious className="-top-2.5 right-2 ml-auto -translate-x-full -translate-y-full md:top-1/2 md:-left-12 md:m-0 md:translate-x-0 md:-translate-y-1/2 lg:md:-left-16" />
          <CarouselNext className="-top-2.5 right-0 ml-auto -translate-y-full md:top-1/2 md:-right-12 md:m-0 md:-translate-y-1/2 lg:md:-right-16" />
        </Carousel>

        {/* Pagination */}
        <div className="mt-6 flex items-center justify-center gap-2">
          {Array.from({ length: count }).map((_, index) => (
            <div
              className={cn(
                "h-2 w-2 rounded-full",
                current === index + 1 ? "bg-primary" : "bg-primary/20"
              )}
              key={index}
            />
          ))}
        </div>
      </div>
    </div>
  );
};

export default Testimonials;
```
