ToroUI

Carousel

A scrollable content area with previous/next navigation and keyboard support.


A composable carousel built on Embla Carousel. Supports horizontal and vertical orientations, plugins, and exposes the underlying API for advanced use cases.

1
2
3
4
5
import {
  Carousel,
  CarouselContent,
  CarouselItem,
  CarouselNext,
  CarouselPrevious,
} from "@/components/ui/carousel"

export default function CarouselDemo() {
  return (
    <Carousel className="w-full max-w-xs">
      <CarouselContent>
        {Array.from({ length: 5 }).map((_, index) => (
          <CarouselItem key={index}>
            <div className="flex aspect-square items-center justify-center rounded-md border p-6">
              <span className="text-4xl font-semibold">{index + 1}</span>
            </div>
          </CarouselItem>
        ))}
      </CarouselContent>
      <CarouselPrevious />
      <CarouselNext />
    </Carousel>
  )
}

Anatomy

import {
  Carousel,
  CarouselContent,
  CarouselItem,
  CarouselPrevious,
  CarouselNext,
} from "@/components/ui/carousel"
<Carousel>
  <CarouselContent>
    <CarouselItem>Slide 1</CarouselItem>
    <CarouselItem>Slide 2</CarouselItem>
    <CarouselItem>Slide 3</CarouselItem>
  </CarouselContent>
  <CarouselPrevious />
  <CarouselNext />
</Carousel>

Examples

<Carousel>
  <CarouselContent>
    {Array.from({ length: 5 }).map((_, i) => (
      <CarouselItem key={i}>
        <div className="flex aspect-square items-center justify-center rounded-md border text-4xl font-semibold">
          {i + 1}
        </div>
      </CarouselItem>
    ))}
  </CarouselContent>
  <CarouselPrevious />
  <CarouselNext />
</Carousel>

Multiple items per view

Use the basis utility on CarouselItem to show multiple slides at once.

<Carousel>
  <CarouselContent>
    {items.map((item) => (
      <CarouselItem key={item} className="basis-1/3">
        <Card>{item}</Card>
      </CarouselItem>
    ))}
  </CarouselContent>
  <CarouselPrevious />
  <CarouselNext />
</Carousel>

Vertical orientation

<Carousel orientation="vertical" className="max-h-64">
  <CarouselContent>
    <CarouselItem>Slide 1</CarouselItem>
    <CarouselItem>Slide 2</CarouselItem>
    <CarouselItem>Slide 3</CarouselItem>
  </CarouselContent>
  <CarouselPrevious />
  <CarouselNext />
</Carousel>

Accessing the API

Use setApi to get access to the Embla Carousel API instance for programmatic control.

function Demo() {
  const [api, setApi] = React.useState<CarouselApi>()

  React.useEffect(() => {
    if (!api) return
    api.on("select", () => {
      console.log("Current slide:", api.selectedScrollSnap())
    })
  }, [api])

  return (
    <Carousel setApi={setApi}>
      <CarouselContent>
        <CarouselItem>Slide 1</CarouselItem>
        <CarouselItem>Slide 2</CarouselItem>
      </CarouselContent>
    </Carousel>
  )
}

API Reference

The root component. Sets up the Embla Carousel instance and provides context to child components.

PropTypeDefaultDescription
orientation"horizontal" | "vertical""horizontal"The scroll direction.
optsCarouselOptionsEmbla Carousel options.
pluginsCarouselPluginEmbla Carousel plugins.
setApi(api: CarouselApi) => voidCallback to receive the Embla API instance.
classNamestring
childrenReactNode

CarouselContent

The scrollable container. Renders an overflow-hidden wrapper around a flex row (or column).

PropTypeDefault
classNamestring
childrenReactNode

CarouselItem

A single slide. Defaults to basis-full so each item takes the full carousel width.

PropTypeDefault
classNamestring
childrenReactNode

CarouselPrevious

A button that scrolls to the previous slide. Absolutely positioned to the left (or top in vertical mode).

PropTypeDefaultDescription
variantButtonVariant"outline"The button variant.
sizeButtonSize"icon-sm"The button size.
classNamestring

CarouselNext

A button that scrolls to the next slide. Absolutely positioned to the right (or bottom in vertical mode).

PropTypeDefaultDescription
variantButtonVariant"outline"The button variant.
sizeButtonSize"icon-sm"The button size.
classNamestring