Carousel
A carousel with motion and swipe built using Embla.
Preview
Installation
npx sigma-ui@latest add carouselUsage
<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.
<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.
<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.
<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 />.
<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:
<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 />.
<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:
<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.
<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:
npm i embla-carousel-autoplay<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
Carousel
Props
| Prop | Type | Default |
|---|---|---|
optsEmbla Carousel options, such as loop or align. | MaybeRef<Partial<OptionsType>> | - |
pluginsEmbla Carousel plugins, such as autoplay. | MaybeRef<CreatePluginType<LoosePluginType, {}>[]> | - |
orientationScroll axis of the carousel; also sets which arrow keys navigate it. | "vertical" | "horizontal" | "horizontal" |
Events
| Event | Payload |
|---|---|
init-apiEmitted on mount with the Embla Carousel API instance. | [payload: EmblaCarouselType] |
Slots
| Slot | Scope |
|---|---|
defaultThe 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
| Method | Type |
|---|---|
carouselRefTemplate ref of the Embla viewport element. | HTMLElement |
carouselApiEmbla Carousel API instance, available after mount. | EmblaCarouselType |
canScrollPrevWhether the carousel can scroll to a previous slide. | boolean |
canScrollNextWhether the carousel can scroll to a next slide. | boolean |
scrollPrevScrolls to the previous slide. | () => void |
scrollNextScrolls to the next slide. | () => void |
CarouselContent
Slots
| Slot | Scope |
|---|---|
defaultThe content of the component. | - |
CarouselItem
Slots
| Slot | Scope |
|---|---|
defaultThe content of the component. | - |
CarouselPrevious
Props
| Prop | Type | Default |
|---|---|---|
label | string | "Previous Slide" |
Slots
| Slot | Scope |
|---|---|
defaultThe content of the component. | - |
CarouselNext
Props
| Prop | Type | Default |
|---|---|---|
label | string | "Next Slide" |
Slots
| Slot | Scope |
|---|---|
defaultThe 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".
| Key | Description |
|---|---|
| Tab | Moves focus to the carousel, then to the previous and next buttons. |
| ArrowLeft | When the horizontal carousel is focused, scrolls to the previous slide. |
| ArrowRight | When the horizontal carousel is focused, scrolls to the next slide. |
| ArrowUp | When the vertical carousel is focused, scrolls to the previous slide. |
| ArrowDown | When the vertical carousel is focused, scrolls to the next slide. |
| Enter | Activates the focused previous or next button. |