Carousel
Import
import { Carousel, CarouselDots, CarouselNavigation } from "@dr-max/ui/carousel"
The entry carries its own precompiled CSS (including the styles of the Button, Icon, Spinner and Text parts it composes) — no extra style imports needed. The track itself is powered by keen-slider.
Usage
Pass the data through the slides array — the default slot is a scoped slot that receives each entry as slide, so the carousel stays agnostic about what a slide looks like. slides-per-page sets how many slides form one page:
<script setup lang="ts">
import { Carousel } from "@dr-max/ui/carousel"
const slides = ["One", "Two", "Three", "Four", "Five", "Six"]
</script>
<template>
<Carousel :slides="slides" :slides-per-page="3" slide-class="px-1">
<template #default="{ slide }">
<div class="flex h-32 items-center justify-center rounded-lg bg-blue-50">
{{ slide }}
</div>
</template>
</Carousel>
</template>
Controls
The #controls scoped slot receives the paging state and callbacks (currentPage, pageCount, showPage, showPrevPage, showNextPage, …) — wire them to CarouselDots and CarouselNavigation. A separate #pagination slot receives pageIds, currentPage, pageCount and showPage for fully custom pagination:
<script setup lang="ts">
import { Carousel, CarouselDots, CarouselNavigation } from "@dr-max/ui/carousel"
const slides = ["One", "Two", "Three", "Four", "Five", "Six"]
</script>
<template>
<Carousel :slides="slides" :slides-per-page="3" slide-class="px-1">
<template #default="{ slide }">
<div class="flex h-32 items-center justify-center rounded-lg bg-blue-50">
{{ slide }}
</div>
</template>
<template #controls="{ showPrevPage, showNextPage, showPage, pageCount, currentPage }">
<div class="relative mt-2 flex min-h-12 items-center">
<CarouselDots :current-page="currentPage" :page-count="pageCount" @show-page="showPage" />
<CarouselNavigation class="right-1" @click-prev="showPrevPage" @click-next="showNextPage" />
</div>
</template>
</Carousel>
</template>
Scrollbar
force-scrollbar renders a progress scrollbar below the track — useful when dots would be too many:
<template>
<Carousel :slides="slides" :slides-per-page="3" force-scrollbar>
<template #default="{ slide }">…</template>
</Carousel>
</template>
Autoplay and loop
autoplay-interval advances the carousel automatically (milliseconds, zero disables it — the default), and loop lets the track continue past the last slide:
<template>
<Carousel :slides="slides" :autoplay-interval="5000" loop>
<template #default="{ slide }">…</template>
</Carousel>
</template>
Responsive
breakpoints takes keen-slider responsive options, and per-view-auto sizes slides by their own width instead of slides-per-page:
<template>
<Carousel
:slides="slides"
:slides-per-page="1"
:breakpoints="{
'(min-width: 768px)': { slides: { perView: 2 } },
'(min-width: 1024px)': { slides: { perView: 4 } }
}"
>
<template #default="{ slide }">…</template>
</Carousel>
</template>
Every slide element carries aria-roledescription — localize it with the slide-role-description prop.