Carousel

A carousel with motion and swipe built using Embla.

@react.component
let make = () =>
  <Carousel className="w-full max-w-[12rem] sm:max-w-xs">

About

The carousel component is built using the Embla Carousel library.

Installation

npx shadcn@latest add @rescript-shadcn/Carousel

Usage

<Carousel>
  <Carousel.Content>
    <Carousel.Item> {"..."->React.string} </Carousel.Item>
    <Carousel.Item> {"..."->React.string} </Carousel.Item>
    <Carousel.Item> {"..."->React.string} </Carousel.Item>
  </Carousel.Content>
  <Carousel.Previous />
  <Carousel.Next />
</Carousel>

Examples

Sizes

To set the size of the items, you can use the basis utility class on the <CarouselItem />.

@react.component
let make = () =>
  <Carousel opts={align: "start"} className="w-full max-w-[12rem] sm:max-w-xs md:max-w-sm">
// 33% of the carousel width.
<Carousel>
  <CarouselContent>
    <CarouselItem className="basis-1/3">...</CarouselItem>
    <CarouselItem className="basis-1/3">...</CarouselItem>
    <CarouselItem className="basis-1/3">...</CarouselItem>
  </CarouselContent>
</Carousel>
// 50% on small screens and 33% on larger screens.
<Carousel>
  <CarouselContent>
    <CarouselItem className="md:basis-1/2 lg:basis-1/3">...</CarouselItem>
    <CarouselItem className="md:basis-1/2 lg:basis-1/3">...</CarouselItem>
    <CarouselItem className="md:basis-1/2 lg:basis-1/3">...</CarouselItem>
  </CarouselContent>
</Carousel>

Spacing

To set the spacing between the items, we use a pl-[VALUE] utility on the <CarouselItem /> and a negative -ml-[VALUE] on the <CarouselContent />.

@react.component
let make = () =>
  <Carousel className="w-full max-w-[12rem] sm:max-w-xs md:max-w-sm">
<Carousel>
  <CarouselContent className="-ml-4">
    <CarouselItem className="pl-4">...</CarouselItem>
    <CarouselItem className="pl-4">...</CarouselItem>
    <CarouselItem className="pl-4">...</CarouselItem>
  </CarouselContent>
</Carousel>
<Carousel>
  <CarouselContent className="-ml-2 md:-ml-4">
    <CarouselItem className="pl-2 md:pl-4">...</CarouselItem>
    <CarouselItem className="pl-2 md:pl-4">...</CarouselItem>
    <CarouselItem className="pl-2 md:pl-4">...</CarouselItem>
  </CarouselContent>
</Carousel>

Orientation

Use the orientation prop to set the orientation of the carousel.

@react.component
let make = () =>
  <Carousel
<Carousel orientation=Vertical>
  <CarouselContent>
    <CarouselItem>...</CarouselItem>
    <CarouselItem>...</CarouselItem>
    <CarouselItem>...</CarouselItem>
  </CarouselContent>
</Carousel>

Options

You can pass options to the carousel using the opts prop. See the Embla Carousel docs for more information.

<Carousel
  opts={{
    align: "start",
    loop: true,
  }}
>
  <CarouselContent>
    <CarouselItem>...</CarouselItem>
    <CarouselItem>...</CarouselItem>
    <CarouselItem>...</CarouselItem>
  </CarouselContent>
</Carousel>

API

Use a state and the setApi props to get an instance of the carousel API.

@@directive("'use client'")

@react.component
@react.component
let make = () => {
  const (api, setApi) = React.useState(() => None)
  const (current, setCurrent) = React.useState(() => 0)
  const (count, setCount) = React.useState(() => 0)
 
  React.useEffect(() => {
    api->Option.forEach(api => {
      setCount(_ => api->Carousel.Api.scrollSnapList->Array.length)
      setCurrent(_ => api->Carousel.Api.selectedScrollSnap + 1)
      api->Carousel.Api.on("select", () => {
        setCurrent(_ => api->Carousel.Api.selectedScrollSnap + 1)
      })
    })
    None
  }, [api])
 
  <Carousel setApi={api => setApi(_ => api)}>
    <Carousel.Content>
      <Carousel.Item>...</Carousel.Item>
      <Carousel.Item>...</Carousel.Item>
      <Carousel.Item>...</Carousel.Item>
    </Carousel.Content>
  </Carousel>
}

Events

You can listen to events using the api instance from setApi.

module Example = {
  @react.component
  let make = () => {
    let (api, setApi) = React.useState(() => None)
 
    React.useEffect(() => {
 
      api->Option.forEach(api => api->Carousel.Api.on("select", api => {
        // Do something on select.
      }))
      None
    }, [api])
 
    <Carousel setApi={setApi}>
      <CarouselContent>
        <CarouselItem>...</CarouselItem>
        <CarouselItem>...</CarouselItem>
        <CarouselItem>...</CarouselItem>
      </CarouselContent>
    </Carousel>
    }
}

See the Embla Carousel docs for more information on using events.

Plugins

You can use the plugins prop to add plugins to the carousel.

type autoplayOptions = {delay: int}
@module("embla-carousel-autoplay")
external autoplay: autplayOptions => Carousel.emblaPlugin = "default"
 
module Example = {
  @react.component
  let make = () => {
    <Carousel
      plugins={[
        autoplay({
          delay: 2000,
        }),
      ]}
    >
      // ...
    </Carousel>
  }
}
@@directive("'use client'")

type autoplayOptions = {delay: int, stopOnInteraction: bool}

API Reference

See the Embla Carousel docs for more information on props and plugins.