# Relay Carousel: Customer Stories

> Workshop owners on the invoicing app they run their shop on. It plays by itself and holds while you point at it; pull the strip, use the arrows or click a card to pass the lead.

A shadcn/ui block from the [@keyframeui](https://keyframeui.com/?utm_source=shadcn.exchange) registry, listed on [shadcn.exchange](https://shadcn.exchange/r/keyframeui/relay-carousel-demo).

- Page, with a live preview: https://shadcn.exchange/r/keyframeui/relay-carousel-demo
- Screenshot: https://shadcn.exchange/shot/keyframeui/relay-carousel-demo/light.png
- Registry item: https://keyframeui.com/r/relay-carousel-demo.json
- Categories: carousel, testimonials, motion
- Listed: 2026-10-27, source last changed 2026-10-27

## Install

```bash
npx shadcn@latest add https://shadcn.exchange/r/keyframeui/relay-carousel-demo.json
```

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

## Dependencies

- Registry items: `https://keyframeui.com/r/relay-carousel.json`

## Notes from the registry

Live preview, examples and props: https://keyframeui.com/components/relay-carousel#relay-carousel-demo

## Files

### `registry/demos/relay-carousel-demo.tsx`

```tsx
import { RelayCarousel, RelayCarouselItem } from "@/components/ui/relay-carousel";

const makers = [
  {
    name: "Joaquim Carvalho",
    role: "Ceramicist, Barro Studio",
    label: "Ceramics · Porto",
    quote:
      "I used to spend Sunday nights matching invoices to kiln loads. Now an order comes in and the glaze stock counts itself down.",
    photo: "1753164725926-dc4de5911e61",
    alt: "A bearded potter in a clay-streaked apron raising a tall vase on the wheel",
  },
  {
    name: "Tomasz Wiśniewski",
    role: "Owner, Kruszon Bakery",
    label: "Bakery · Kraków",
    quote:
      "Our cafés reorder from a link I sent them once. I know what to bake tomorrow before the ovens have cooled down.",
    photo: "1772758632504-361aa9d14a19",
    alt: "A baker sliding flatbreads into a brick oven, rounds of dough waiting in front",
  },
  {
    name: "Gareth Lloyd",
    role: "Woodcarver, Grain & Gauge",
    label: "Woodwork · Leeds",
    quote:
      "Every commission keeps its timber, hours and deposit on one page. Quoting a carved panel takes ten minutes, not an evening.",
    photo: "1783669081274-3db07e6ec196",
    alt: "A woodcarver chiseling a relief panel at a cluttered bench under a desk lamp",
  },
  {
    name: "Kenji Arai",
    role: "Roaster, Hiraku Coffee",
    label: "Coffee · Osaka",
    quote:
      "Green beans, roast days and wholesale orders finally talk to each other. I buy sacks when the numbers say so, not when I panic.",
    photo: "1607681034512-1c9c5fbda608",
    alt: "A roaster in ear defenders checking freshly roasted beans under a magnifier lamp",
  },
  {
    name: "Lena Hoffmann",
    role: "Florist, Stiel",
    label: "Flowers · Leipzig",
    quote:
      "Wedding season used to live on sticky notes. This year every bouquet had its stems, its order and its invoice before the bride did.",
    photo: "1531058240690-006c446962d8",
    alt: "A florist at the counter of her flower shop, seen through the plants",
  },
  {
    name: "Idris Hale",
    role: "Leatherworker, Hale & Hide",
    label: "Leather · Bristol",
    quote:
      "Custom orders, hides and the balance owed sit on the same screen. I've stopped losing deposits in the gap between them.",
    photo: "1534126511673-b6899657816a",
    alt: "A craftsman stitching a leather strap on an industrial sewing machine",
  },
  {
    name: "Rafael Moreno",
    role: "Mechanic, Cadena Cycles",
    label: "Repairs · Valencia",
    quote:
      "Customers get a message when their bike is ready and pay from the link. My bench stays clear, and so does my inbox.",
    photo: "1675798227643-da319f8ee8f7",
    alt: "A mechanic's hands tightening the crank on a black bicycle frame",
  },
  {
    name: "Ewan MacLeod",
    role: "Printer, Low Tide Press",
    label: "Screen print · Edinburgh",
    quote:
      "A poster run has twelve proofs and three deposits. Field & Fold keeps all of it straight, so I can keep my hands inky.",
    photo: "1456456496250-d5e7c0a9b44d",
    alt: "A printmaker pulling ink across a silkscreen by the window",
  },
];

const photo = (id: string) =>
  `https://images.unsplash.com/photo-${id}?auto=format&fit=crop&w=880&h=840&q=80`;

export function RelayCarouselDemo() {
  return (
    <div className="flex min-h-[var(--demo-height,auto)] w-full flex-col justify-center overflow-hidden rounded-2xl border border-zinc-200 bg-white py-14 text-zinc-950 sm:py-20 dark:border-zinc-800 dark:bg-zinc-950 dark:text-zinc-50">
      <RelayCarousel
        aria-labelledby="relay-makers-heading"
        autoPlay={7000}
        heading={
          <h2
            id="relay-makers-heading"
            className="text-[2rem] leading-[1.02] font-semibold tracking-[-0.035em] text-balance @2xl:text-5xl"
          >
            Small shops,
            <br />
            <span className="text-zinc-400 dark:text-zinc-500">steady books.</span>
          </h2>
        }
      >
        {makers.map((maker) => (
          <RelayCarouselItem
            key={maker.name}
            name={maker.name}
            role={maker.role}
            label={maker.label}
            quote={maker.quote}
            image={photo(maker.photo)}
            alt={maker.alt}
          />
        ))}
      </RelayCarousel>
    </div>
  );
}
```
