Skip to main content

Carousel

  • Component overview: A carousel/slider component with declarative items API, built on embla-carousel-react.
  • Interaction: Supports keyboard arrow keys, drag-to-scroll, horizontal/vertical orientation.
  • Implementation note: ui/carousel retains the embla structural skeleton; the design layer provides the declarative items API.

Basic Usage

Pass an items array to declare slide content — the simplest way to use the carousel.

Result
Loading...
Live Editor
<Carousel
  items={[
    {
      key: '1',
      content: (
        <div style={{ background: '#f0f0f0', borderRadius: 8, padding: 40, textAlign: 'center' }}>
          Slide 1
        </div>
      ),
    },
    {
      key: '2',
      content: (
        <div style={{ background: '#e8e8e8', borderRadius: 8, padding: 40, textAlign: 'center' }}>
          Slide 2
        </div>
      ),
    },
    {
      key: '3',
      content: (
        <div style={{ background: '#e0e0e0', borderRadius: 8, padding: 40, textAlign: 'center' }}>
          Slide 3
        </div>
      ),
    },
  ]}
/>

Multiple Slides Per View

Use slidesPerView to control how many slides are visible at once.

Result
Loading...
Live Editor
<Carousel
  slidesPerView={3}
  items={Array.from({ length: 6 }, (_, i) => ({
    key: i,
    content: (
      <div style={{ background: '#f0f0f0', borderRadius: 8, padding: 24, textAlign: 'center' }}>
        Item {i + 1}
      </div>
    ),
  }))}
/>

Hidden Controls

Set showControls={false} to hide the prev/next arrows, useful for drag-only or autoplay scenarios.

Result
Loading...
Live Editor
<Carousel
  showControls={false}
  items={[
    {
      key: '1',
      content: (
        <div style={{ background: '#f0f0f0', borderRadius: 8, padding: 40, textAlign: 'center' }}>
          Drag to switch 1
        </div>
      ),
    },
    {
      key: '2',
      content: (
        <div style={{ background: '#e8e8e8', borderRadius: 8, padding: 40, textAlign: 'center' }}>
          Drag to switch 2
        </div>
      ),
    },
    {
      key: '3',
      content: (
        <div style={{ background: '#e0e0e0', borderRadius: 8, padding: 40, textAlign: 'center' }}>
          Drag to switch 3
        </div>
      ),
    },
  ]}
/>

Vertical Orientation

Set orientation="vertical" to switch to a vertical carousel.

Result
Loading...
Live Editor
<div style={{ height: 200 }}>
  <Carousel
    orientation="vertical"
    items={[
      {
        key: '1',
        content: (
          <div style={{ background: '#f0f0f0', borderRadius: 8, padding: 40, textAlign: 'center' }}>
            Vertical 1
          </div>
        ),
      },
      {
        key: '2',
        content: (
          <div style={{ background: '#e8e8e8', borderRadius: 8, padding: 40, textAlign: 'center' }}>
            Vertical 2
          </div>
        ),
      },
      {
        key: '3',
        content: (
          <div style={{ background: '#e0e0e0', borderRadius: 8, padding: 40, textAlign: 'center' }}>
            Vertical 3
          </div>
        ),
      },
    ]}
  />
</div>

Autoplay

Set autoplay to enable automatic slide advancement. Pass true for the default 4-second interval, or a number (ms) for a custom interval. Combine with opts={{ loop: true }} for infinite looping.

Result
Loading...
Live Editor
<Carousel
  autoplay={3000}
  opts={{ loop: true }}
  items={Array.from({ length: 5 }, (_, i) => ({
    key: i,
    content: (
      <div style={{ background: '#f0f0f0', borderRadius: 8, padding: 40, textAlign: 'center' }}>
        Slide {i + 1}
      </div>
    ),
  }))}
/>

Props

PropTypeDefaultDescription
itemsCarouselItemEntry[]-Declarative slide items
showControlsbooleantrueShow prev/next arrow buttons
slidesPerViewnumber1Number of visible slides
autoplayboolean | numberfalseAuto-advance slides. true = 4000ms, or pass ms
prevIconReactNode<ChevronLeftIcon />Custom previous button icon
nextIconReactNode<ChevronRightIcon />Custom next button icon
orientation'horizontal' | 'vertical''horizontal'Scroll direction
optsEmblaCarouselOptions-Embla carousel options (e.g. loop, align)
pluginsEmblaCarouselPlugin[]-Embla carousel plugins
setApi(api: CarouselApi) => void-Callback to receive the carousel API instance
gapstring-Gap class applied to each item
contentClassNamestring-Custom class for the content wrapper
itemClassNamestring-Custom class for each item wrapper
classNamestring-Custom class for the root container

CarouselItemEntry

FieldTypeDefaultDescription
keystring | number-Unique identifier
contentReactNode-Slide content
classNamestring-Custom class for this item