Carousel

A carousel with motion and swipe built using Embla.

Preview ​

Installation ​

npx sigma-ui@latest add carousel

Usage ​

vue
<script setup lang="ts">
import {
  Carousel,
  CarouselContent,
  CarouselItem,
  CarouselNext,
  CarouselPrevious,
} from '@/components/ui/carousel';
</script>

<template>
  <Carousel>
    <CarouselContent>
      <CarouselItem>...</CarouselItem>
      <CarouselItem>...</CarouselItem>
      <CarouselItem>...</CarouselItem>
    </CarouselContent>
    <CarouselPrevious />
    <CarouselNext />
  </Carousel>
</template>

The carousel is built on Embla Carousel, which handles the scrolling and swiping. More examples are in the Embla Carousel docs.

Options ​

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

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

Events ​

You can listen to events using the API. To get the API instance use the @init-api emit method on the <Carousel /> component.

vue
<script setup lang="ts">
import { nextTick, ref, watch } from 'vue';
import type { CarouselApi } from '@/components/ui/carousel';

const api = ref<CarouselApi>();

function setApi(val: CarouselApi) {
  api.value = val;
}

const stop = watch(api, (api) => {
  if (!api) {
    return;
  }

  // Watch only once
  nextTick(() => stop());

  api.on('select', () => {
    // Do something on select
  });
});
</script>

<template>
  <Carousel @init-api="setApi">
    ...
  </Carousel>
</template>

More about events: Embla Carousel docs | Events

Slot props ​

You can get the reactive slot props like carouselRef, canScrollNext, canScrollPrev, scrollNext, and scrollPrev using the v-slot directive on the <Carousel /> component to extend the functionality.

vue
<template>
  <Carousel v-slot="{ canScrollNext, canScrollPrev }">
    ...
    <CarouselPrevious v-if="canScrollPrev" />
    <CarouselNext v-if="canScrollNext" />
  </Carousel>
</template>

Examples ​

Basic ​

Sizes ​

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

vue
<template>
  <!-- 33% of the carousel width. -->
  <Carousel>
    <CarouselContent>
      <CarouselItem class="basis-1/3">...</CarouselItem>
      <CarouselItem class="basis-1/3">...</CarouselItem>
      <CarouselItem class="basis-1/3">...</CarouselItem>
    </CarouselContent>
  </Carousel>
</template>

Responsive:

vue
<template>
  <!-- 50% on small screens and 33% on larger screens. -->
  <Carousel>
    <CarouselContent>
      <CarouselItem class="md:basis-1/2 lg:basis-1/3">...</CarouselItem>
      <CarouselItem class="md:basis-1/2 lg:basis-1/3">...</CarouselItem>
      <CarouselItem class="md:basis-1/2 lg:basis-1/3">...</CarouselItem>
    </CarouselContent>
  </Carousel>
</template>

Spacing ​

In this component, the easiest way to set the spacing between items is to use a positive padding on the <CarouselItem /> and a negative margin on the <CarouselContent />.

vue
<template>
  <Carousel>
    <CarouselContent class="-ml-4">
      <CarouselItem class="pl-4">
        ...
      </CarouselItem>
      <CarouselItem class="pl-4">
        ...
      </CarouselItem>
      <CarouselItem class="pl-4">
        ...
      </CarouselItem>
    </CarouselContent>
  </Carousel>
</template>

Responsive:

vue
<template>
  <Carousel>
    <CarouselContent class="-ml-2 md:-ml-4">
      <CarouselItem class="pl-2 md:pl-4">
        ...
      </CarouselItem>
      <CarouselItem class="pl-2 md:pl-4">
        ...
      </CarouselItem>
      <CarouselItem class="pl-2 md:pl-4">
        ...
      </CarouselItem>
    </CarouselContent>
  </Carousel>
</template>

Orientation ​

Use the orientation prop to set the orientation of the carousel to vertical or horizontal.

Thumbnails ​

API ​

Use the @init-api emit method on the <Carousel /> component to get the instance of the API.

You can also access it by setting a template ref on the <Carousel /> component.

vue
<script setup lang="ts">
const carouselContainerRef = ref<InstanceType<typeof Carousel> | null>(null);

function accessApi() {
  carouselContainerRef.value?.carouselApi.on('select', () => {});
}
</script>

<template>
  <Carousel ref="carouselContainerRef">
    ...
  </Carousel>
</template>

Plugins ​

You can use the plugins prop to add plugins to the carousel. Install the plugin package first:

bash
npm i embla-carousel-autoplay
vue
<script setup lang="ts">
import Autoplay from 'embla-carousel-autoplay';
</script>

<template>
  <Carousel
    class="w-full max-w-xs"
    :plugins="[Autoplay({
      delay: 2000,
    })]"
  >
    ...
  </Carousel>
</template>

More about plugins: Embla Carousel docs | Plugins

API Reference ​

Props

PropType Default
opts

Embla Carousel options, such as loop or align.

MaybeRef<Partial<OptionsType>>-
plugins

Embla Carousel plugins, such as autoplay.

MaybeRef<CreatePluginType<LoosePluginType, {}>[]>-
orientation

Scroll axis of the carousel; also sets which arrow keys navigate it.

"vertical" | "horizontal""horizontal"

Events

EventPayload
init-api

Emitted on mount with the Embla Carousel API instance.

[payload: EmblaCarouselType]

Slots

SlotScope
default

The content of the component.

{ carouselRef: Ref<HTMLElement, HTMLElement>; carouselApi: Ref<EmblaCarouselType, EmblaCarouselType>; canScrollPrev: Ref<boolean, boolean>; canScrollNext: Ref<boolean, boolean>; scrollPrev: () => void; scrollNext: () => void; orientation: "vertical" | "horizontal"; }

Methods

MethodType
carouselRef

Template ref of the Embla viewport element.

HTMLElement
carouselApi

Embla Carousel API instance, available after mount.

EmblaCarouselType
canScrollPrev

Whether the carousel can scroll to a previous slide.

boolean
canScrollNext

Whether the carousel can scroll to a next slide.

boolean
scrollPrev

Scrolls to the previous slide.

() => void
scrollNext

Scrolls to the next slide.

() => void

CarouselContent ​

Slots

SlotScope
default

The content of the component.

-

CarouselItem ​

Slots

SlotScope
default

The content of the component.

-

CarouselPrevious ​

Props

PropType Default
label
string"Previous Slide"

Slots

SlotScope
default

The content of the component.

-

CarouselNext ​

Props

PropType Default
label
string"Next Slide"

Slots

SlotScope
default

The content of the component.

-

Accessibility ​

Follows the Carousel WAI-ARIA design pattern: the root is a focusable region with aria-roledescription="carousel", and each item is a group with aria-roledescription="slide".

KeyDescription
TabMoves focus to the carousel, then to the previous and next buttons.
ArrowLeftWhen the horizontal carousel is focused, scrolls to the previous slide.
ArrowRightWhen the horizontal carousel is focused, scrolls to the next slide.
ArrowUpWhen the vertical carousel is focused, scrolls to the previous slide.
ArrowDownWhen the vertical carousel is focused, scrolls to the next slide.
EnterActivates the focused previous or next button.
Edit this page on GitHub