# Carousel Standard 2 - Carousel with Thumbnails

> Carousel with Thumbnails using shadcn Carousel with thumbnail navigation.

A shadcn/ui block from the [@shadcnblocks](https://shadcnblocks.com) registry, listed on [shadcn.exchange](https://shadcn.exchange/r/shadcnblocks/carousel-carousel-standard-2).

- Page, with a live preview: https://shadcn.exchange/r/shadcnblocks/carousel-carousel-standard-2
- Screenshot: https://abzjhwgwpdpz7ua5.public.blob.vercel-storage.com/shots/shadcnblocks/carousel-carousel-standard-2-light-f0b620833b3a1fb9.png
- Registry item: https://shadcnblocks.com/r/carousel-carousel-standard-2.json
- Listed: 2026-10-13, source last changed 2026-10-13

## Install

```bash
npx shadcn@latest add https://shadcnblocks.com/r/carousel-carousel-standard-2.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: `button`, `carousel`

## Files

### `example/carousel/carousel-standard-2.tsx`

```tsx
"use client";

import { useState } from "react";

import { Button } from "@/components/ui/button";
import {
  Carousel,
  type CarouselApi,
  CarouselContent,
  CarouselItem,
} from "@/components/ui/carousel";

export const title = "Carousel with Thumbnails";

const slides = [
  {
    id: 1,
    image:
      "https://deifkwefumgah.cloudfront.net/shadcnblocks/image-set/modern/photos/photo-1-16x9.jpg",
  },
  {
    id: 2,
    image:
      "https://deifkwefumgah.cloudfront.net/shadcnblocks/image-set/modern/photos/photo-2-16x9.jpg",
  },
  {
    id: 3,
    image:
      "https://deifkwefumgah.cloudfront.net/shadcnblocks/image-set/modern/photos/photo-3-16x9.jpg",
  },
  {
    id: 4,
    image:
      "https://deifkwefumgah.cloudfront.net/shadcnblocks/image-set/modern/photos/photo-4-16x9.jpg",
  },
  {
    id: 5,
    image:
      "https://deifkwefumgah.cloudfront.net/shadcnblocks/image-set/modern/photos/photo-5-16x9.jpg",
  },
];

const Example = () => {
  const [api, setApi] = useState<CarouselApi>();
  const [current, setCurrent] = useState(0);

  const handleApiChange = (newApi: CarouselApi) => {
    setApi(newApi);

    if (newApi) {
      setCurrent(newApi.selectedScrollSnap());

      newApi.on("select", () => {
        setCurrent(newApi.selectedScrollSnap());
      });
    }
  };

  return (
    <div className="mx-auto w-full max-w-md space-y-4">
      <Carousel setApi={handleApiChange}>
        <CarouselContent>
          {slides.map((slide) => (
            <CarouselItem key={slide.id}>
              <div className="flex aspect-[2/1] items-center justify-center rounded-md border bg-background">
                <span className="text-4xl font-semibold">{slide.id}</span>
              </div>
            </CarouselItem>
          ))}
        </CarouselContent>
      </Carousel>

      <div className="flex justify-center gap-2">
        {slides.map((slide, index) => (
          <Button
            key={slide.id}
            onClick={() => api?.scrollTo(index)}
            variant={current === index ? "default" : "outline"}
          >
            {slide.id}
          </Button>
        ))}
      </div>
    </div>
  );
};

export default Example;
```
