- Accordion
- Alert
- Alert Dialog
- Aspect Ratio
- Avatar
- Badge
- Breadcrumb
- Button
- Button Group
- Calendar
- Card
- Carousel
- Chart
- Checkbox
- Collapsible
- Combobox
- Command
- Context Menu
- Data Table
- Date Picker
- Dialog
- Drawer
- Dropdown Menu
- Empty
- Field
- Hover Card
- Input
- Input Group
- Input OTP
- Item
- Kbd
- Label
- Menubar
- Native Select
- Navigation Menu
- Pagination
- Popover
- Progress
- Radio Group
- Resizable
- Scroll Area
- Select
- Separator
- Sheet
- Sidebar
- Skeleton
- Slider
- Sonner
- Spinner
- Switch
- Table
- Tabs
- Textarea
- Toast
- Toggle
- Toggle Group
- Tooltip
- Typography
About#
The carousel component is built using the Embla Carousel library.
Installation#
pnpm dlx shadcn@latest add @force-ui-vue/carousel
Usage#
<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>Composition#
Use the following composition to build a Carousel:
Carousel
├── CarouselContent
│ ├── CarouselItem
│ └── CarouselItem
├── CarouselPrevious
└── CarouselNextExamples#
Sizes#
To set the size of the items, you can use the basis utility class on the <CarouselItem />.
// 33% of the carousel width.
<template>
<Carousel>
<CarouselContent>
<CarouselItem class="basis-1/3"> ... </CarouselItem>
<CarouselItem class="basis-1/3"> ... </CarouselItem>
<CarouselItem class="basis-1/3"> ... </CarouselItem>
</CarouselContent>
</Carousel>
</template>// 50% on small screens and 33% on larger screens.
<template>
<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#
To set the spacing between the items, we use a pl-[VALUE] utility on the <CarouselItem /> and a negative -ml-[VALUE] 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><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.
<Carousel orientation="vertical | horizontal">
...
</Carousel>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>API#
Method 1#
Use the @init-api emit method on <Carousel /> component to set the instance of the API.
Method 2#
You can access it through 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>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 { useCarousel } 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 or use watchOnce() in @vueuse/core
nextTick(() => stop())
api.on("select", () => {
// Do something on select.
})
})
</script>
<template>
<Carousel @init-api="setApi"> ... </Carousel>
</template>See the Embla Carousel docs for more information on using events.
Plugins#
You can use the plugins prop to add plugins to the carousel.
pnpm add 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>See the Embla Carousel docs for more information on using plugins.
RTL#
To enable RTL support in Force UI, see the RTL configuration guide.
When localizing the carousel for RTL languages, you need to set the direction option in the :opts prop to match the text direction. This ensures the carousel scrolls in the correct direction.
<template>
<Carousel
:dir="dir"
:opts="{
direction: dir,
}"
>
<CarouselContent>
<CarouselItem>...</CarouselItem>
<CarouselItem>...</CarouselItem>
<CarouselItem>...</CarouselItem>
</CarouselContent>
<CarouselPrevious class="rtl:rotate-180" />
<CarouselNext class="rtl:rotate-180" />
</Carousel>
</template>The direction option accepts "ltr" or "rtl" and should match the :dir prop value. You may also want to rotate the navigation buttons using the rtl:rotate-180 class to ensure they point in the correct direction.
Slot Props#
You can get the reactive slot props like carouselRef, canScrollNext..Prev, scrollNext..Prev using the v-slot directive in the <Carousel v-slot="slotProps" /> component to extend the functionality.
<template>
<Carousel v-slot="{ canScrollNext, canScrollPrev }">
...
<CarouselPrevious v-if="canScrollPrev" />
<CarouselNext v-if="canScrollNext" />
</Carousel>
</template>API Reference#
See the Embla Carousel docs for more information on props and plugins.