Carousel
An interactive slideshow component for cycling through elements.
Features
- Native CSS Scroll Snap integration for smooth, performant animations
- Flexible orientation support (horizontal and vertical layouts)
- Customizable slide alignment (start, center, or end positions)
- Multi-slide display capabilities for complex layouts
- Automatic playback with configurable looping behavior
- Adjustable slide spacing and gap controls
Anatomy
To set up the carousel correctly, you'll need to understand its anatomy and how we name its parts.
Each part includes a
data-partattribute to help identify them in the DOM.
Examples
Learn how to use the Carousel component in your project. Let's take a look at the most basic example:
import { Carousel } from '@ark-ui/react/carousel'
export const Basic = () => {
const images = Array.from({ length: 5 }, (_, i) => `https://picsum.photos/seed/${i + 1}/500/300`)
return (
<Carousel.Root defaultPage={0} slideCount={images.length}>
<Carousel.Control>
<Carousel.PrevTrigger>Previous</Carousel.PrevTrigger>
<Carousel.NextTrigger>Next</Carousel.NextTrigger>
</Carousel.Control>
<Carousel.IndicatorGroup>
{images.map((_, index) => (
<Carousel.Indicator key={index} index={index} />
))}
</Carousel.IndicatorGroup>
<Carousel.ItemGroup>
{images.map((image, index) => (
<Carousel.Item key={index} index={index}>
<img src={image} alt={`Slide ${index}`} />
</Carousel.Item>
))}
</Carousel.ItemGroup>
</Carousel.Root>
)
}
import { Carousel } from '@ark-ui/solid/carousel'
import { Index } from 'solid-js'
const images = Array.from({ length: 5 }, (_, i) => `https://picsum.photos/seed/${i + 1}/500/300`)
export const Basic = () => {
return (
<Carousel.Root slideCount={images.length}>
<Carousel.Control>
<Carousel.PrevTrigger>Previous</Carousel.PrevTrigger>
<Carousel.NextTrigger>Next</Carousel.NextTrigger>
</Carousel.Control>
<Carousel.IndicatorGroup>
<Index each={images}>{(_, index) => <Carousel.Indicator index={index} />}</Index>
</Carousel.IndicatorGroup>
<Carousel.ItemGroup>
<Index each={images}>
{(image, index) => (
<Carousel.Item index={index}>
<img src={image()} alt={`Slide ${index}`} />
</Carousel.Item>
)}
</Index>
</Carousel.ItemGroup>
</Carousel.Root>
)
}
<script setup lang="ts">
import { Carousel } from '@ark-ui/vue/carousel'
const images = Array.from({ length: 5 }, (_, i) => `https://picsum.photos/seed/${i + 1}/500/300`)
</script>
<template>
<Carousel.Root :slide-count="images.length">
<Carousel.Control>
<Carousel.PrevTrigger>Previous</Carousel.PrevTrigger>
<Carousel.NextTrigger>Next</Carousel.NextTrigger>
</Carousel.Control>
<Carousel.IndicatorGroup>
<Carousel.Indicator v-for="(_, idx) in images" :key="idx" :index="idx" />
</Carousel.IndicatorGroup>
<Carousel.ItemGroup>
<Carousel.Item v-for="(image, idx) in images" :key="idx" :index="idx">
<img :src="image" alt="" :style="{ height: '300px', width: '100%', objectFit: 'cover' }" />
</Carousel.Item>
</Carousel.ItemGroup>
</Carousel.Root>
</template>
<script>
import { Carousel } from '@ark-ui/svelte/carousel'
const images = Array.from({ length: 5 }, (_, i) => `https://picsum.photos/seed/${i + 1}/500/300`)
</script>
<Carousel.Root defaultPage={0} slideCount={images.length}>
<Carousel.Control>
<Carousel.PrevTrigger>Previous</Carousel.PrevTrigger>
<Carousel.NextTrigger>Next</Carousel.NextTrigger>
</Carousel.Control>
<Carousel.IndicatorGroup>
{#each images as _, index}
<Carousel.Indicator {index} />
{/each}
</Carousel.IndicatorGroup>
<Carousel.ItemGroup>
{#each images as image, index}
<Carousel.Item {index}>
<img src={image} alt="Slide {index}" />
</Carousel.Item>
{/each}
</Carousel.ItemGroup>
</Carousel.Root>
Controlled
To create a controlled Carousel component, you can manage the state of the carousel using the page prop and update it
when the onPageChange event handler is called:
import { Carousel } from '@ark-ui/react/carousel'
import { useState } from 'react'
const images = Array.from({ length: 5 }, (_, i) => `https://picsum.photos/seed/${i + 1}/500/300`)
export const Controlled = () => {
const [page, setPage] = useState(0)
return (
<Carousel.Root slideCount={images.length} page={page} onPageChange={(e) => setPage(e.page)}>
<Carousel.Control>
<Carousel.PrevTrigger>Previous</Carousel.PrevTrigger>
<Carousel.NextTrigger>Next</Carousel.NextTrigger>
</Carousel.Control>
<Carousel.IndicatorGroup>
{images.map((_, index) => (
<Carousel.Indicator key={index} index={index} />
))}
</Carousel.IndicatorGroup>
<Carousel.ItemGroup>
{images.map((image, index) => (
<Carousel.Item key={index} index={index}>
<img src={image} alt={`Slide ${index}`} />
</Carousel.Item>
))}
</Carousel.ItemGroup>
</Carousel.Root>
)
}
import { Carousel } from '@ark-ui/solid/carousel'
import { Index, createSignal } from 'solid-js'
const images = Array.from({ length: 5 }, (_, i) => `https://picsum.photos/seed/${i + 1}/500/300`)
export const Controlled = () => {
const [page, setPage] = createSignal(0)
return (
<Carousel.Root slideCount={images.length} page={page()} onPageChange={(details) => setPage(details.page)}>
<Carousel.Control>
<Carousel.PrevTrigger>Previous</Carousel.PrevTrigger>
<Carousel.NextTrigger>Next</Carousel.NextTrigger>
</Carousel.Control>
<Carousel.IndicatorGroup>
<Index each={images}>{(_, index) => <Carousel.Indicator index={index} />}</Index>
</Carousel.IndicatorGroup>
<Carousel.ItemGroup>
<Index each={images}>
{(image, index) => (
<Carousel.Item index={index}>
<img src={image()} alt={`Slide ${index}`} />
</Carousel.Item>
)}
</Index>
</Carousel.ItemGroup>
</Carousel.Root>
)
}
<script setup lang="ts">
import { Carousel } from '@ark-ui/vue/carousel'
import { ref } from 'vue'
const images = Array.from({ length: 5 }, (_, i) => `https://picsum.photos/seed/${i + 1}/500/300`)
const page = ref(0)
</script>
<template>
<Carousel.Root v-model:page="page" :slide-count="images.length">
<Carousel.Control>
<Carousel.PrevTrigger>Previous</Carousel.PrevTrigger>
<Carousel.NextTrigger>Next</Carousel.NextTrigger>
</Carousel.Control>
<Carousel.IndicatorGroup>
<Carousel.Indicator v-for="(_, idx) in images" :key="idx" :index="idx" />
</Carousel.IndicatorGroup>
<Carousel.ItemGroup>
<Carousel.Item v-for="(image, idx) in images" :key="idx" :index="idx">
<img :src="image" alt="" />
</Carousel.Item>
</Carousel.ItemGroup>
</Carousel.Root>
<p>Current page: {{ page }}</p>
</template>
<script>
import { Carousel } from '@ark-ui/svelte/carousel'
const images = Array.from({ length: 5 }, (_, i) => `https://picsum.photos/seed/${i + 1}/500/300`)
let page = $state(0)
</script>
<div>
<div>Current page: {page}</div>
<Carousel.Root bind:page slideCount={images.length}>
<Carousel.Control>
<Carousel.PrevTrigger>Previous</Carousel.PrevTrigger>
<Carousel.NextTrigger>Next</Carousel.NextTrigger>
</Carousel.Control>
<Carousel.IndicatorGroup>
{#each images as _, index}
<Carousel.Indicator {index} />
{/each}
</Carousel.IndicatorGroup>
<Carousel.ItemGroup>
{#each images as image, index}
<Carousel.Item {index}>
<img src={image} alt="Slide {index}" />
</Carousel.Item>
{/each}
</Carousel.ItemGroup>
</Carousel.Root>
</div>
Root Provider
Use the useCarousel hook to create the carousel store and pass it to the Carousel.RootProvider component. This
allows you to have maximum control over the carousel programmatically.
import { Carousel, useCarousel } from '@ark-ui/react/carousel'
const images = Array.from({ length: 5 }, (_, i) => `https://picsum.photos/seed/${i + 1}/500/300`)
export const RootProvider = () => {
const carousel = useCarousel({ slideCount: images.length })
return (
<>
<button onClick={() => carousel.scrollToIndex(2)}>Scroll to #3</button>
<Carousel.RootProvider value={carousel}>
<Carousel.Control>
<Carousel.PrevTrigger>Previous</Carousel.PrevTrigger>
<Carousel.NextTrigger>Next</Carousel.NextTrigger>
</Carousel.Control>
<Carousel.IndicatorGroup>
{images.map((_, index) => (
<Carousel.Indicator key={index} index={index} />
))}
</Carousel.IndicatorGroup>
<Carousel.ItemGroup>
{images.map((image, index) => (
<Carousel.Item key={index} index={index}>
<img src={image} alt={`Slide ${index}`} />
</Carousel.Item>
))}
</Carousel.ItemGroup>
</Carousel.RootProvider>
</>
)
}
import { Carousel, useCarousel } from '@ark-ui/solid/carousel'
import { Index } from 'solid-js'
const images = Array.from({ length: 5 }, (_, i) => `https://picsum.photos/seed/${i + 1}/500/300`)
export const RootProvider = () => {
const carousel = useCarousel({ slideCount: images.length })
return (
<>
<button onClick={() => carousel().scrollToIndex(2)}>Scroll to #3</button>
<Carousel.RootProvider value={carousel}>
<Carousel.Control>
<Carousel.PrevTrigger>Previous</Carousel.PrevTrigger>
<Carousel.NextTrigger>Next</Carousel.NextTrigger>
</Carousel.Control>
<Carousel.IndicatorGroup>
<Index each={images}>{(_, index) => <Carousel.Indicator index={index} />}</Index>
</Carousel.IndicatorGroup>
<Carousel.ItemGroup>
<Index each={images}>
{(image, index) => (
<Carousel.Item index={index}>
<img src={image()} alt={`Slide ${index}`} />
</Carousel.Item>
)}
</Index>
</Carousel.ItemGroup>
</Carousel.RootProvider>
</>
)
}
<script setup lang="ts">
import { Carousel, useCarousel } from '@ark-ui/vue/carousel'
const images = Array.from({ length: 5 }, (_, i) => `https://picsum.photos/seed/${i + 1}/500/300`)
const carousel = useCarousel({ slideCount: images.length })
</script>
<template>
<button @click="carousel.scrollToIndex(2)">Scroll to #3</button>
<Carousel.RootProvider :value="carousel">
<Carousel.Control>
<Carousel.PrevTrigger>Previous</Carousel.PrevTrigger>
<Carousel.NextTrigger>Next</Carousel.NextTrigger>
</Carousel.Control>
<Carousel.IndicatorGroup>
<Carousel.Indicator v-for="(_, idx) in images" :key="idx" :index="idx" />
</Carousel.IndicatorGroup>
<Carousel.ItemGroup>
<Carousel.Item v-for="(image, idx) in images" :key="idx" :index="idx">
<img :src="image" alt="" />
</Carousel.Item>
</Carousel.ItemGroup>
</Carousel.RootProvider>
</template>
<script>
import { Carousel, useCarousel } from '@ark-ui/svelte/carousel'
const images = Array.from({ length: 5 }, (_, i) => `https://picsum.photos/seed/${i + 1}/500/300`)
const id = $props.id()
const carousel = useCarousel({
id,
defaultPage: 0,
slideCount: images.length,
})
</script>
<div>
<div>Current page: {carousel().page}</div>
<Carousel.RootProvider value={carousel}>
<Carousel.Control>
<Carousel.PrevTrigger>Previous</Carousel.PrevTrigger>
<Carousel.NextTrigger>Next</Carousel.NextTrigger>
</Carousel.Control>
<Carousel.IndicatorGroup>
{#each images as _, index}
<Carousel.Indicator {index} />
{/each}
</Carousel.IndicatorGroup>
<Carousel.ItemGroup>
{#each images as image, index}
<Carousel.Item {index}>
<img src={image} alt="Slide {index}" />
</Carousel.Item>
{/each}
</Carousel.ItemGroup>
</Carousel.RootProvider>
</div>
If you're using the
Carousel.RootProvidercomponent, you don't need to use theCarousel.Rootcomponent.
Autoplay
Pass the autoplay and loop props to Carousel.Root to make the carousel play automatically.
Note: Adding
loopensures the carousel keeps going after the last slide.
import { Carousel } from '@ark-ui/react/carousel'
const images = Array.from({ length: 5 }, (_, i) => `https://picsum.photos/seed/${i + 1}/500/300`)
export const Autoplay = () => {
return (
<Carousel.Root slideCount={images.length} autoplay loop>
<Carousel.Control>
<Carousel.AutoplayTrigger>
<Carousel.Context>{({ isPlaying }) => (isPlaying ? 'Pause' : 'Play')}</Carousel.Context>
</Carousel.AutoplayTrigger>
</Carousel.Control>
<Carousel.IndicatorGroup>
{images.map((_, index) => (
<Carousel.Indicator key={index} index={index} />
))}
</Carousel.IndicatorGroup>
<Carousel.ItemGroup>
{images.map((image, index) => (
<Carousel.Item key={index} index={index}>
<img src={image} alt={`Slide ${index}`} />
</Carousel.Item>
))}
</Carousel.ItemGroup>
</Carousel.Root>
)
}
import { Carousel } from '@ark-ui/solid/carousel'
import { Index } from 'solid-js'
const images = Array.from({ length: 5 }, (_, i) => `https://picsum.photos/seed/${i + 1}/500/300`)
export const Autoplay = () => {
return (
<Carousel.Root slideCount={images.length} autoplay loop>
<Carousel.Control>
<Carousel.AutoplayTrigger>
<Carousel.Context>{(carousel) => (carousel().isPlaying ? 'Pause' : 'Play')}</Carousel.Context>
</Carousel.AutoplayTrigger>
</Carousel.Control>
<Carousel.IndicatorGroup>
<Index each={images}>{(_, index) => <Carousel.Indicator index={index} />}</Index>
</Carousel.IndicatorGroup>
<Carousel.ItemGroup>
<Index each={images}>
{(image, index) => (
<Carousel.Item index={index}>
<img src={image()} alt={`Slide ${index}`} />
</Carousel.Item>
)}
</Index>
</Carousel.ItemGroup>
</Carousel.Root>
)
}
<script setup lang="ts">
import { Carousel } from '@ark-ui/vue/carousel'
const images = Array.from({ length: 5 }, (_, i) => `https://picsum.photos/seed/${i + 1}/500/300`)
</script>
<template>
<Carousel.Root :slide-count="images.length" autoplay loop>
<Carousel.Control>
<Carousel.AutoplayTrigger>
<Carousel.Context v-slot="context">
{{ context.isPlaying ? 'Pause' : 'Play' }}
</Carousel.Context>
</Carousel.AutoplayTrigger>
</Carousel.Control>
<Carousel.IndicatorGroup>
<Carousel.Indicator v-for="(_, idx) in images" :key="idx" :index="idx" />
</Carousel.IndicatorGroup>
<Carousel.ItemGroup>
<Carousel.Item v-for="(image, idx) in images" :key="idx" :index="idx">
<img :src="image" alt="" />
</Carousel.Item>
</Carousel.ItemGroup>
</Carousel.Root>
</template>
<script>
import { Carousel } from '@ark-ui/svelte/carousel'
const images = Array.from({ length: 5 }, (_, i) => `https://picsum.photos/seed/${i + 1}/500/300`)
</script>
<Carousel.Root defaultPage={0} slideCount={images.length} autoplay={{ delay: 3000 }}>
<Carousel.Control>
<Carousel.PrevTrigger>Previous</Carousel.PrevTrigger>
<Carousel.AutoplayTrigger>Toggle Autoplay</Carousel.AutoplayTrigger>
<Carousel.NextTrigger>Next</Carousel.NextTrigger>
</Carousel.Control>
<Carousel.IndicatorGroup>
{#each images as _, index}
<Carousel.Indicator {index} />
{/each}
</Carousel.IndicatorGroup>
<Carousel.ItemGroup>
{#each images as image, index}
<Carousel.Item {index}>
<img src={image} alt="Slide {index}" />
</Carousel.Item>
{/each}
</Carousel.ItemGroup>
</Carousel.Root>
Pause on Hover
This feature isn't built-in, but you can use the play() and pause() methods from Carousel.Context to implement
pause on hover.
Add the autoplay and loop props to Carousel.Root, then attach onPointerOver and onPointerLeave handlers to
Carousel.ItemGroup that call api.pause() and api.play() respectively.
import { Carousel } from '@ark-ui/react/carousel'
const images = Array.from({ length: 5 }, (_, i) => `https://picsum.photos/seed/${i + 1}/500/300`)
export const PauseOnHover = () => {
return (
<Carousel.Root slideCount={images.length} autoplay loop>
<Carousel.Control>
<Carousel.Context>{({ isPlaying }) => `Autoplay is: ${isPlaying ? 'playing' : 'paused'}`}</Carousel.Context>
</Carousel.Control>
<Carousel.Context>
{(api) => (
<Carousel.ItemGroup onPointerOver={() => api.pause()} onPointerLeave={() => api.play()}>
{images.map((image, index) => (
<Carousel.Item key={index} index={index}>
<img src={image} alt={`Slide ${index}`} />
</Carousel.Item>
))}
</Carousel.ItemGroup>
)}
</Carousel.Context>
<Carousel.IndicatorGroup>
{images.map((_, index) => (
<Carousel.Indicator key={index} index={index} />
))}
</Carousel.IndicatorGroup>
</Carousel.Root>
)
}
import { Carousel } from '@ark-ui/solid/carousel'
import { Index } from 'solid-js'
const images = Array.from({ length: 5 }, (_, i) => `https://picsum.photos/seed/${i + 1}/500/300`)
export const PauseOnHover = () => {
return (
<Carousel.Root slideCount={images.length} autoplay loop>
<Carousel.Control>
<Carousel.Context>
{(carousel) => `Autoplay is: ${carousel().isPlaying ? 'playing' : 'paused'}`}
</Carousel.Context>
</Carousel.Control>
<Carousel.Context>
{(api) => (
<Carousel.ItemGroup onPointerOver={() => api().pause()} onPointerLeave={() => api().play()}>
<Index each={images}>
{(image, index) => (
<Carousel.Item index={index}>
<img src={image()} alt={`Slide ${index}`} />
</Carousel.Item>
)}
</Index>
</Carousel.ItemGroup>
)}
</Carousel.Context>
<Carousel.IndicatorGroup>
<Index each={images}>{(_, index) => <Carousel.Indicator index={index} />}</Index>
</Carousel.IndicatorGroup>
</Carousel.Root>
)
}
<script setup lang="ts">
import { Carousel } from '@ark-ui/vue/carousel'
const images = Array.from({ length: 5 }, (_, i) => `https://picsum.photos/seed/${i + 1}/500/300`)
</script>
<template>
<Carousel.Root :slide-count="images.length" autoplay loop>
<Carousel.Control>
<Carousel.Context v-slot="context">Autoplay is: {{ context.isPlaying ? 'playing' : 'paused' }}</Carousel.Context>
</Carousel.Control>
<Carousel.Context v-slot="api">
<Carousel.ItemGroup @pointerover="api.pause()" @pointerleave="api.play()">
<Carousel.Item v-for="(image, idx) in images" :key="idx" :index="idx">
<img :src="image" alt="" />
</Carousel.Item>
</Carousel.ItemGroup>
</Carousel.Context>
<Carousel.IndicatorGroup>
<Carousel.Indicator v-for="(_, idx) in images" :key="idx" :index="idx" />
</Carousel.IndicatorGroup>
</Carousel.Root>
</template>
<script>
import { Carousel } from '@ark-ui/svelte/carousel'
const images = Array.from({ length: 5 }, (_, i) => `https://picsum.photos/seed/${i + 1}/500/300`)
</script>
<Carousel.Root slideCount={images.length} autoplay loop>
<Carousel.Control>
<Carousel.Context>
{#snippet render(api)}
Autoplay is: {api().isPlaying ? 'playing' : 'paused'}
{/snippet}
</Carousel.Context>
</Carousel.Control>
<Carousel.Context>
{#snippet render(api)}
<Carousel.ItemGroup onpointerover={() => api().pause()} onpointerleave={() => api().play()}>
{#each images as image, index}
<Carousel.Item {index}>
<img src={image} alt="Slide {index}" />
</Carousel.Item>
{/each}
</Carousel.ItemGroup>
{/snippet}
</Carousel.Context>
<Carousel.IndicatorGroup>
{#each images as _, index}
<Carousel.Indicator {index} />
{/each}
</Carousel.IndicatorGroup>
</Carousel.Root>
Custom Indicators
Replace default indicator dots with custom content by wrapping Carousel.IndicatorGroup in Carousel.Context. Use
api.page to determine the active indicator and render image thumbnails for each slide:
import { Carousel } from '@ark-ui/react/carousel'
export const CustomIndicator = () => {
const images = Array.from({ length: 5 }, (_, i) => `https://picsum.photos/seed/${i + 1}/500/300`)
return (
<Carousel.Root defaultPage={0} slideCount={images.length}>
<Carousel.Control>
<Carousel.PrevTrigger>Previous</Carousel.PrevTrigger>
<Carousel.NextTrigger>Next</Carousel.NextTrigger>
</Carousel.Control>
<Carousel.ItemGroup>
{images.map((image, index) => (
<Carousel.Item key={index} index={index}>
<img src={image} alt={`Slide ${index}`} style={{ width: '100%', height: '300px', objectFit: 'cover' }} />
</Carousel.Item>
))}
</Carousel.ItemGroup>
<Carousel.Context>
{(api) => (
<Carousel.IndicatorGroup style={{ display: 'flex', gap: '8px', marginTop: '16px' }}>
{images.map((image, index) => (
<Carousel.Indicator key={index} index={index}>
<img
src={image}
alt={`Thumbnail ${index}`}
style={{
width: '60px',
height: '40px',
objectFit: 'cover',
cursor: 'pointer',
border: api.page === index ? '2px solid #0066ff' : '2px solid transparent',
borderRadius: '4px',
opacity: api.page === index ? 1 : 0.6,
transition: 'all 0.2s',
}}
/>
</Carousel.Indicator>
))}
</Carousel.IndicatorGroup>
)}
</Carousel.Context>
</Carousel.Root>
)
}
import { Carousel } from '@ark-ui/solid/carousel'
import { Index } from 'solid-js'
const images = Array.from({ length: 5 }, (_, i) => `https://picsum.photos/seed/${i + 1}/500/300`)
export const CustomIndicator = () => {
return (
<Carousel.Root slideCount={images.length}>
<Carousel.Control>
<Carousel.PrevTrigger>Previous</Carousel.PrevTrigger>
<Carousel.NextTrigger>Next</Carousel.NextTrigger>
</Carousel.Control>
<Carousel.ItemGroup>
<Index each={images}>
{(image, index) => (
<Carousel.Item index={index}>
<img
src={image()}
alt={`Slide ${index}`}
style={{ width: '100%', height: '300px', 'object-fit': 'cover' }}
/>
</Carousel.Item>
)}
</Index>
</Carousel.ItemGroup>
<Carousel.Context>
{(api) => (
<Carousel.IndicatorGroup style={{ display: 'flex', gap: '8px', 'margin-top': '16px' }}>
<Index each={images}>
{(image, index) => (
<Carousel.Indicator index={index}>
<img
src={image()}
alt={`Thumbnail ${index}`}
style={{
width: '60px',
height: '40px',
'object-fit': 'cover',
cursor: 'pointer',
border: api().page === index ? '2px solid #0066ff' : '2px solid transparent',
'border-radius': '4px',
opacity: api().page === index ? 1 : 0.6,
transition: 'all 0.2s',
}}
/>
</Carousel.Indicator>
)}
</Index>
</Carousel.IndicatorGroup>
)}
</Carousel.Context>
</Carousel.Root>
)
}
<script setup lang="ts">
import { Carousel } from '@ark-ui/vue/carousel'
const images = Array.from({ length: 5 }, (_, i) => `https://picsum.photos/seed/${i + 1}/500/300`)
</script>
<template>
<Carousel.Root :slide-count="images.length">
<Carousel.Control>
<Carousel.PrevTrigger>Previous</Carousel.PrevTrigger>
<Carousel.NextTrigger>Next</Carousel.NextTrigger>
</Carousel.Control>
<Carousel.ItemGroup>
<Carousel.Item v-for="(image, idx) in images" :key="idx" :index="idx">
<img :src="image" alt="" :style="{ height: '300px', width: '100%', objectFit: 'cover' }" />
</Carousel.Item>
</Carousel.ItemGroup>
<Carousel.Context v-slot="api">
<Carousel.IndicatorGroup :style="{ display: 'flex', gap: '8px', marginTop: '16px' }">
<Carousel.Indicator v-for="(image, idx) in images" :key="idx" :index="idx">
<img
:src="image"
:alt="`Thumbnail ${idx}`"
:style="{
width: '60px',
height: '40px',
objectFit: 'cover',
cursor: 'pointer',
border: api.page === idx ? '2px solid #0066ff' : '2px solid transparent',
borderRadius: '4px',
opacity: api.page === idx ? 1 : 0.6,
transition: 'all 0.2s',
}"
/>
</Carousel.Indicator>
</Carousel.IndicatorGroup>
</Carousel.Context>
</Carousel.Root>
</template>
<script>
import { Carousel } from '@ark-ui/svelte/carousel'
const images = Array.from({ length: 5 }, (_, i) => `https://picsum.photos/seed/${i + 1}/500/300`)
</script>
<Carousel.Root defaultPage={0} slideCount={images.length}>
<Carousel.Control>
<Carousel.PrevTrigger>Previous</Carousel.PrevTrigger>
<Carousel.NextTrigger>Next</Carousel.NextTrigger>
</Carousel.Control>
<Carousel.ItemGroup>
{#each images as image, index}
<Carousel.Item {index}>
<img src={image} alt="Slide {index}" style="width: 100%; height: 300px; object-fit: cover;" />
</Carousel.Item>
{/each}
</Carousel.ItemGroup>
<Carousel.Context>
{#snippet render(api)}
<Carousel.IndicatorGroup style="display: flex; gap: 8px; margin-top: 16px;">
{#each images as image, index}
<Carousel.Indicator {index}>
<img
src={image}
alt="Thumbnail {index}"
style="
width: 60px;
height: 40px;
object-fit: cover;
cursor: pointer;
border: {api().page === index ? '2px solid #0066ff' : '2px solid transparent'};
border-radius: 4px;
opacity: {api().page === index ? 1 : 0.6};
transition: all 0.2s;
"
/>
</Carousel.Indicator>
{/each}
</Carousel.IndicatorGroup>
{/snippet}
</Carousel.Context>
</Carousel.Root>
Vertical Orientation
Set the orientation="vertical" prop on Carousel.Root to change the carousel from horizontal to vertical scrolling.
This is useful for vertical galleries or content feeds.
import { Carousel } from '@ark-ui/react/carousel'
export const Vertical = () => {
const images = Array.from({ length: 5 }, (_, i) => `https://picsum.photos/seed/${i + 1}/500/300`)
return (
<Carousel.Root defaultPage={0} orientation="vertical" slideCount={images.length}>
<Carousel.Control>
<Carousel.PrevTrigger>Previous</Carousel.PrevTrigger>
<Carousel.NextTrigger>Next</Carousel.NextTrigger>
</Carousel.Control>
<Carousel.IndicatorGroup>
{images.map((_, index) => (
<Carousel.Indicator key={index} index={index} />
))}
</Carousel.IndicatorGroup>
<Carousel.ItemGroup>
{images.map((image, index) => (
<Carousel.Item key={index} index={index}>
<img src={image} alt={`Slide ${index}`} />
</Carousel.Item>
))}
</Carousel.ItemGroup>
</Carousel.Root>
)
}
import { Carousel } from '@ark-ui/solid/carousel'
import { Index } from 'solid-js'
const images = Array.from({ length: 5 }, (_, i) => `https://picsum.photos/seed/${i + 1}/500/300`)
export const Vertical = () => {
return (
<Carousel.Root orientation="vertical" slideCount={images.length}>
<Carousel.Control>
<Carousel.PrevTrigger>Previous</Carousel.PrevTrigger>
<Carousel.NextTrigger>Next</Carousel.NextTrigger>
</Carousel.Control>
<Carousel.IndicatorGroup>
<Index each={images}>{(_, index) => <Carousel.Indicator index={index} />}</Index>
</Carousel.IndicatorGroup>
<Carousel.ItemGroup>
<Index each={images}>
{(image, index) => (
<Carousel.Item index={index}>
<img src={image()} alt={`Slide ${index}`} />
</Carousel.Item>
)}
</Index>
</Carousel.ItemGroup>
</Carousel.Root>
)
}
<script setup lang="ts">
import { Carousel } from '@ark-ui/vue/carousel'
const images = Array.from({ length: 5 }, (_, i) => `https://picsum.photos/seed/${i + 1}/500/300`)
</script>
<template>
<Carousel.Root orientation="vertical" :slide-count="images.length">
<Carousel.Control>
<Carousel.PrevTrigger>Previous</Carousel.PrevTrigger>
<Carousel.NextTrigger>Next</Carousel.NextTrigger>
</Carousel.Control>
<Carousel.IndicatorGroup>
<Carousel.Indicator v-for="(_, idx) in images" :key="idx" :index="idx" />
</Carousel.IndicatorGroup>
<Carousel.ItemGroup>
<Carousel.Item v-for="(image, idx) in images" :key="idx" :index="idx">
<img :src="image" alt="" :style="{ height: '300px', width: '100%', objectFit: 'cover' }" />
</Carousel.Item>
</Carousel.ItemGroup>
</Carousel.Root>
</template>
<script>
import { Carousel } from '@ark-ui/svelte/carousel'
const images = Array.from({ length: 5 }, (_, i) => `https://picsum.photos/seed/${i + 1}/500/300`)
</script>
<Carousel.Root defaultPage={0} orientation="vertical" slideCount={images.length}>
<Carousel.Control>
<Carousel.PrevTrigger>Previous</Carousel.PrevTrigger>
<Carousel.NextTrigger>Next</Carousel.NextTrigger>
</Carousel.Control>
<Carousel.IndicatorGroup>
{#each images as _, index}
<Carousel.Indicator {index} />
{/each}
</Carousel.IndicatorGroup>
<Carousel.ItemGroup>
{#each images as image, index}
<Carousel.Item {index}>
<img src={image} alt="Slide {index}" />
</Carousel.Item>
{/each}
</Carousel.ItemGroup>
</Carousel.Root>
Dynamic Slides
Manage slides dynamically by storing them in state and syncing the carousel page. Pass the page prop and
onPageChange handler to Carousel.Root, and update slideCount when slides are added or removed. This demonstrates
bidirectional state synchronization between your component state and the carousel.
import { Carousel } from '@ark-ui/react/carousel'
import { useState } from 'react'
export const DynamicSlides = () => {
const [slides, setSlides] = useState([0, 1, 2, 3, 4])
const [page, setPage] = useState(0)
const addSlide = () => {
setSlides((prevSlides) => {
const max = Math.max(...prevSlides)
return [...prevSlides, max + 1]
})
}
return (
<div>
<Carousel.Root slideCount={slides.length} page={page} onPageChange={(details) => setPage(details.page)}>
<Carousel.Control>
<Carousel.PrevTrigger>Previous</Carousel.PrevTrigger>
<Carousel.NextTrigger>Next</Carousel.NextTrigger>
</Carousel.Control>
<Carousel.IndicatorGroup>
{slides.map((_, index) => (
<Carousel.Indicator key={index} index={index} />
))}
</Carousel.IndicatorGroup>
<Carousel.ItemGroup>
{slides.map((slide, index) => (
<Carousel.Item key={index} index={index}>
<div
style={{
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
width: '100%',
height: '300px',
backgroundColor: `hsl(${(slide * 60) % 360}, 70%, 60%)`,
color: 'white',
fontSize: '24px',
fontWeight: 'bold',
borderRadius: '8px',
}}
>
Slide {slide}
</div>
</Carousel.Item>
))}
</Carousel.ItemGroup>
</Carousel.Root>
<button onClick={addSlide} style={{ marginTop: '16px', padding: '8px 16px', cursor: 'pointer' }}>
Add Slide
</button>
</div>
)
}
import { Carousel } from '@ark-ui/solid/carousel'
import { Index, createSignal } from 'solid-js'
export const DynamicSlides = () => {
const [slides, setSlides] = createSignal([0, 1, 2, 3, 4])
const [page, setPage] = createSignal(0)
const addSlide = () => {
setSlides((prevSlides) => {
const max = Math.max(...prevSlides)
return [...prevSlides, max + 1]
})
}
return (
<div>
<Carousel.Root slideCount={slides().length} page={page()} onPageChange={(details) => setPage(details.page)}>
<Carousel.Control>
<Carousel.PrevTrigger>Previous</Carousel.PrevTrigger>
<Carousel.NextTrigger>Next</Carousel.NextTrigger>
</Carousel.Control>
<Carousel.IndicatorGroup>
<Index each={slides()}>{(_, index) => <Carousel.Indicator index={index} />}</Index>
</Carousel.IndicatorGroup>
<Carousel.ItemGroup>
<Index each={slides()}>
{(slide, index) => (
<Carousel.Item index={index}>
<div
style={{
display: 'flex',
'align-items': 'center',
'justify-content': 'center',
width: '100%',
height: '300px',
'background-color': `hsl(${(slide() * 60) % 360}, 70%, 60%)`,
color: 'white',
'font-size': '24px',
'font-weight': 'bold',
'border-radius': '8px',
}}
>
Slide {slide()}
</div>
</Carousel.Item>
)}
</Index>
</Carousel.ItemGroup>
</Carousel.Root>
<button onClick={addSlide} style={{ 'margin-top': '16px', padding: '8px 16px', cursor: 'pointer' }}>
Add Slide
</button>
</div>
)
}
<script setup lang="ts">
import { Carousel } from '@ark-ui/vue/carousel'
import { ref } from 'vue'
const slides = ref([0, 1, 2, 3, 4])
const page = ref(0)
const addSlide = () => {
const max = Math.max(...slides.value)
slides.value = [...slides.value, max + 1]
}
</script>
<template>
<div>
<Carousel.Root v-model:page="page" :slide-count="slides.length">
<Carousel.Control>
<Carousel.PrevTrigger>Previous</Carousel.PrevTrigger>
<Carousel.NextTrigger>Next</Carousel.NextTrigger>
</Carousel.Control>
<Carousel.IndicatorGroup>
<Carousel.Indicator v-for="(_, idx) in slides" :key="idx" :index="idx" />
</Carousel.IndicatorGroup>
<Carousel.ItemGroup>
<Carousel.Item v-for="(slide, idx) in slides" :key="idx" :index="idx">
<div
:style="{
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
height: '300px',
width: '100%',
backgroundColor: `hsl(${(slide * 60) % 360}, 70%, 60%)`,
color: 'white',
fontSize: '24px',
fontWeight: 'bold',
borderRadius: '8px',
}"
>
Slide {{ slide }}
</div>
</Carousel.Item>
</Carousel.ItemGroup>
</Carousel.Root>
<button @click="addSlide" :style="{ marginTop: '16px', padding: '8px 16px', cursor: 'pointer' }">Add Slide</button>
</div>
</template>
<script>
import { Carousel } from '@ark-ui/svelte/carousel'
let slides = $state([0, 1, 2, 3, 4])
let page = $state(0)
function addSlide() {
const max = Math.max(...slides)
slides = [...slides, max + 1]
}
</script>
<div>
<Carousel.Root bind:page slideCount={slides.length}>
<Carousel.Control>
<Carousel.PrevTrigger>Previous</Carousel.PrevTrigger>
<Carousel.NextTrigger>Next</Carousel.NextTrigger>
</Carousel.Control>
<Carousel.IndicatorGroup>
{#each slides as _, index}
<Carousel.Indicator {index} />
{/each}
</Carousel.IndicatorGroup>
<Carousel.ItemGroup>
{#each slides as slide, index}
<Carousel.Item {index}>
<div
style="
display: flex;
align-items: center;
justify-content: center;
width: 100%;
height: 300px;
background-color: hsl({(slide * 60) % 360}, 70%, 60%);
color: white;
font-size: 24px;
font-weight: bold;
border-radius: 8px;
"
>
Slide {slide}
</div>
</Carousel.Item>
{/each}
</Carousel.ItemGroup>
</Carousel.Root>
<button onclick={addSlide} style="margin-top: 16px; padding: 8px 16px; cursor: pointer;">Add Slide</button>
</div>
Scroll to Slide
Use Carousel.Context to access the carousel API and call api.scrollToIndex(index) to programmatically navigate to a
specific slide. This is useful for creating custom navigation or jump-to-slide functionality.
import { Carousel } from '@ark-ui/react/carousel'
export const ScrollTo = () => {
return (
<Carousel.Root slideCount={5}>
<Carousel.Context>
{(api) => <button onClick={() => api.scrollToIndex(3)}>Go to slide 4</button>}
</Carousel.Context>
<Carousel.ItemGroup>
{Array.from({ length: 5 }, (_, index) => (
<Carousel.Item key={index} index={index}>
<div
style={{
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
width: '100%',
height: '300px',
backgroundColor: '#f0f0f0',
fontSize: '24px',
fontWeight: 'bold',
borderRadius: '8px',
}}
>
Slide {index + 1}
</div>
</Carousel.Item>
))}
</Carousel.ItemGroup>
<Carousel.Control>
<Carousel.PrevTrigger>Previous</Carousel.PrevTrigger>
<Carousel.NextTrigger>Next</Carousel.NextTrigger>
</Carousel.Control>
<Carousel.IndicatorGroup>
{Array.from({ length: 5 }, (_, index) => (
<Carousel.Indicator key={index} index={index} />
))}
</Carousel.IndicatorGroup>
</Carousel.Root>
)
}
import { Carousel } from '@ark-ui/solid/carousel'
import { Index } from 'solid-js'
export const ScrollTo = () => {
return (
<Carousel.Root slideCount={5}>
<Carousel.Context>
{(api) => <button onClick={() => api().scrollToIndex(3)}>Go to slide 4</button>}
</Carousel.Context>
<Carousel.ItemGroup>
<Index each={Array.from({ length: 5 })}>
{(_, index) => (
<Carousel.Item index={index}>
<div
style={{
display: 'flex',
'align-items': 'center',
'justify-content': 'center',
width: '100%',
height: '300px',
'background-color': '#f0f0f0',
'font-size': '24px',
'font-weight': 'bold',
'border-radius': '8px',
}}
>
Slide {index + 1}
</div>
</Carousel.Item>
)}
</Index>
</Carousel.ItemGroup>
<Carousel.Control>
<Carousel.PrevTrigger>Previous</Carousel.PrevTrigger>
<Carousel.NextTrigger>Next</Carousel.NextTrigger>
</Carousel.Control>
<Carousel.IndicatorGroup>
<Index each={Array.from({ length: 5 })}>{(_, index) => <Carousel.Indicator index={index} />}</Index>
</Carousel.IndicatorGroup>
</Carousel.Root>
)
}
<script setup lang="ts">
import { Carousel } from '@ark-ui/vue/carousel'
</script>
<template>
<Carousel.Root :slide-count="5">
<Carousel.Context v-slot="carousel">
<button @click="carousel.scrollToIndex(3)">Go to slide 4</button>
</Carousel.Context>
<Carousel.ItemGroup>
<Carousel.Item v-for="index in 5" :key="index" :index="index - 1">
<div
:style="{
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
width: '100%',
height: '300px',
backgroundColor: '#f0f0f0',
fontSize: '24px',
fontWeight: 'bold',
borderRadius: '8px',
}"
>
Slide {{ index }}
</div>
</Carousel.Item>
</Carousel.ItemGroup>
<Carousel.Control>
<Carousel.PrevTrigger>Previous</Carousel.PrevTrigger>
<Carousel.NextTrigger>Next</Carousel.NextTrigger>
</Carousel.Control>
<Carousel.IndicatorGroup>
<Carousel.Indicator v-for="index in 5" :key="index" :index="index - 1" />
</Carousel.IndicatorGroup>
</Carousel.Root>
</template>
<script>
import { Carousel } from '@ark-ui/svelte/carousel'
</script>
<Carousel.Root slideCount={5}>
<Carousel.Context>
{#snippet render(carousel)}
<button onclick={() => carousel().scrollToIndex(3)}>Go to slide 4</button>
{/snippet}
</Carousel.Context>
<Carousel.ItemGroup>
{#each Array.from({ length: 5 }) as _, index}
<Carousel.Item {index}>
<div
style="display: flex; align-items: center; justify-content: center; width: 100%; height: 300px; background-color: #f0f0f0; font-size: 24px; font-weight: bold; border-radius: 8px;"
>
Slide {index + 1}
</div>
</Carousel.Item>
{/each}
</Carousel.ItemGroup>
<Carousel.Control>
<Carousel.PrevTrigger>Previous</Carousel.PrevTrigger>
<Carousel.NextTrigger>Next</Carousel.NextTrigger>
</Carousel.Control>
<Carousel.IndicatorGroup>
{#each Array.from({ length: 5 }) as _, index}
<Carousel.Indicator {index} />
{/each}
</Carousel.IndicatorGroup>
</Carousel.Root>
Slides Per Page
Display multiple slides simultaneously by setting the slidesPerPage prop on Carousel.Root. Use api.pageSnapPoints
from Carousel.Context to render the correct number of indicators based on pages rather than individual slides. Add the
spacing prop to control the gap between slides.
import { Carousel } from '@ark-ui/react/carousel'
export const SlidesPerPage = () => {
const slides = Array.from({ length: 5 }, (_, i) => i)
return (
<Carousel.Root slideCount={slides.length} slidesPerPage={2} spacing="20px">
<Carousel.Control>
<Carousel.PrevTrigger>Previous</Carousel.PrevTrigger>
<Carousel.NextTrigger>Next</Carousel.NextTrigger>
</Carousel.Control>
<Carousel.ItemGroup>
{slides.map((_, index) => (
<Carousel.Item key={index} index={index}>
<div
style={{
width: '100%',
height: '300px',
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
background: '#f0f0f0',
}}
>
Slide {index + 1}
</div>
</Carousel.Item>
))}
</Carousel.ItemGroup>
<Carousel.Context>
{(api) => (
<Carousel.IndicatorGroup>
{api.pageSnapPoints.map((_, index) => (
<Carousel.Indicator key={index} index={index} />
))}
</Carousel.IndicatorGroup>
)}
</Carousel.Context>
</Carousel.Root>
)
}
import { Carousel } from '@ark-ui/solid/carousel'
import { Index } from 'solid-js'
const slides = Array.from({ length: 5 }, (_, i) => i)
export const SlidesPerPage = () => {
return (
<Carousel.Root slideCount={slides.length} slidesPerPage={2} spacing="20px">
<Carousel.Control>
<Carousel.PrevTrigger>Previous</Carousel.PrevTrigger>
<Carousel.NextTrigger>Next</Carousel.NextTrigger>
</Carousel.Control>
<Carousel.ItemGroup>
<Index each={slides}>
{(_, index) => (
<Carousel.Item index={index}>
<div
style={{
width: '100%',
height: '300px',
display: 'flex',
'align-items': 'center',
'justify-content': 'center',
background: '#f0f0f0',
}}
>
Slide {index + 1}
</div>
</Carousel.Item>
)}
</Index>
</Carousel.ItemGroup>
<Carousel.Context>
{(api) => (
<Carousel.IndicatorGroup>
<Index each={api().pageSnapPoints}>{(_, index) => <Carousel.Indicator index={index} />}</Index>
</Carousel.IndicatorGroup>
)}
</Carousel.Context>
</Carousel.Root>
)
}
<script setup lang="ts">
import { Carousel } from '@ark-ui/vue/carousel'
const slides = Array.from({ length: 5 }, (_, i) => i)
</script>
<template>
<Carousel.Root :slide-count="slides.length" :slides-per-page="2" spacing="20px">
<Carousel.Control>
<Carousel.PrevTrigger>Previous</Carousel.PrevTrigger>
<Carousel.NextTrigger>Next</Carousel.NextTrigger>
</Carousel.Control>
<Carousel.ItemGroup>
<Carousel.Item v-for="(_, idx) in slides" :key="idx" :index="idx">
<div
:style="{
width: '100%',
height: '300px',
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
background: '#f0f0f0',
}"
>
Slide {{ idx + 1 }}
</div>
</Carousel.Item>
</Carousel.ItemGroup>
<Carousel.Context v-slot="api">
<Carousel.IndicatorGroup>
<Carousel.Indicator v-for="(_, idx) in api.pageSnapPoints" :key="idx" :index="idx" />
</Carousel.IndicatorGroup>
</Carousel.Context>
</Carousel.Root>
</template>
<script>
import { Carousel } from '@ark-ui/svelte/carousel'
const slides = Array.from({ length: 5 }, (_, i) => i)
</script>
<Carousel.Root slideCount={slides.length} slidesPerPage={2} spacing="20px">
<Carousel.Control>
<Carousel.PrevTrigger>Previous</Carousel.PrevTrigger>
<Carousel.NextTrigger>Next</Carousel.NextTrigger>
</Carousel.Control>
<Carousel.ItemGroup>
{#each slides as _, index}
<Carousel.Item {index}>
<div
style="width: 100%; height: 300px; display: flex; align-items: center; justify-content: center; background: #f0f0f0;"
>
Slide {index + 1}
</div>
</Carousel.Item>
{/each}
</Carousel.ItemGroup>
<Carousel.Context>
{#snippet render(api)}
<Carousel.IndicatorGroup>
{#each api().pageSnapPoints as _, index}
<Carousel.Indicator {index} />
{/each}
</Carousel.IndicatorGroup>
{/snippet}
</Carousel.Context>
</Carousel.Root>
API Reference
Root
| Prop | Default | Type |
|---|---|---|
slideCount | numberThe total number of slides. Useful for SSR to render the initial ating the snap points. | |
allowMouseDrag | false | booleanWhether to allow scrolling via dragging with mouse |
asChild | booleanUse the provided child element as the default rendered element, combining their props and behavior. For more details, read our Composition guide. | |
autoplay | false | boolean | { delay: number }Whether to scroll automatically. The default delay is 4000ms. |
defaultPage | 0 | numberThe initial page to scroll to when rendered. Use when you don't need to control the page of the carousel. |
ids | Partial<{
root: string
item: (index: number) => string
itemGroup: string
nextTrigger: string
prevTrigger: string
indicatorGroup: string
indicator: (index: number) => string
}>The ids of the elements in the carousel. Useful for composition. | |
inViewThreshold | 0.6 | number | number[]The threshold for determining if an item is in view. |
loop | false | booleanWhether the carousel should loop around. |
onAutoplayStatusChange | (details: AutoplayStatusDetails) => voidFunction called when the autoplay status changes. | |
onDragStatusChange | (details: DragStatusDetails) => voidFunction called when the drag status changes. | |
onPageChange | (details: PageChangeDetails) => voidFunction called when the page changes. | |
orientation | 'horizontal' | 'horizontal' | 'vertical'The orientation of the element. |
padding | stringDefines the extra space added around the scrollable area, enabling nearby items to remain partially in view. | |
page | numberThe controlled page of the carousel. | |
slidesPerMove | 'auto' | number | 'auto'The number of slides to scroll at a time. When set to `auto`, the number of slides to scroll is determined by the `slidesPerPage` property. |
slidesPerPage | 1 | numberThe number of slides to show at a time. |
snapType | 'mandatory' | 'proximity' | 'mandatory'The snap type of the item. |
spacing | '0px' | stringThe amount of space between items. |
translations | IntlTranslationsThe localized messages to use. |
| CSS Variable | Description |
|---|---|
--slides-per-page | The number of slides visible per page |
--slide-spacing | The spacing between slides |
--slide-item-size | The calculated size of each slide item |
| Data Attribute | Value |
|---|---|
[data-scope] | carousel |
[data-part] | root |
[data-orientation] | The orientation of the carousel |
AutoplayTrigger
| Prop | Default | Type |
|---|---|---|
asChild | booleanUse the provided child element as the default rendered element, combining their props and behavior. For more details, read our Composition guide. |
| Data Attribute | Value |
|---|---|
[data-scope] | carousel |
[data-part] | autoplay-trigger |
[data-orientation] | The orientation of the autoplaytrigger |
[data-pressed] | Present when pressed |
Control
| Prop | Default | Type |
|---|---|---|
asChild | booleanUse the provided child element as the default rendered element, combining their props and behavior. For more details, read our Composition guide. |
| Data Attribute | Value |
|---|---|
[data-scope] | carousel |
[data-part] | control |
[data-orientation] | The orientation of the control |
IndicatorGroup
| Prop | Default | Type |
|---|---|---|
asChild | booleanUse the provided child element as the default rendered element, combining their props and behavior. For more details, read our Composition guide. |
| Data Attribute | Value |
|---|---|
[data-scope] | carousel |
[data-part] | indicator-group |
[data-orientation] | The orientation of the indicatorgroup |
Indicator
| Prop | Default | Type |
|---|---|---|
index | numberThe index of the indicator. | |
asChild | booleanUse the provided child element as the default rendered element, combining their props and behavior. For more details, read our Composition guide. | |
readOnly | false | booleanWhether the indicator is read only. |
| Data Attribute | Value |
|---|---|
[data-scope] | carousel |
[data-part] | indicator |
[data-orientation] | The orientation of the indicator |
[data-index] | The index of the item |
[data-readonly] | Present when read-only |
[data-current] | Present when current |
ItemGroup
| Prop | Default | Type |
|---|---|---|
asChild | booleanUse the provided child element as the default rendered element, combining their props and behavior. For more details, read our Composition guide. |
| Data Attribute | Value |
|---|---|
[data-scope] | carousel |
[data-part] | item-group |
[data-orientation] | The orientation of the item |
[data-dragging] | Present when in the dragging state |
Item
| Prop | Default | Type |
|---|---|---|
index | numberThe index of the item. | |
asChild | booleanUse the provided child element as the default rendered element, combining their props and behavior. For more details, read our Composition guide. | |
snapAlign | 'start' | 'center' | 'end' | 'start'The snap alignment of the item. |
| Data Attribute | Value |
|---|---|
[data-scope] | carousel |
[data-part] | item |
[data-index] | The index of the item |
[data-inview] | Present when in viewport |
[data-orientation] | The orientation of the item |
NextTrigger
| Prop | Default | Type |
|---|---|---|
asChild | booleanUse the provided child element as the default rendered element, combining their props and behavior. For more details, read our Composition guide. |
| Data Attribute | Value |
|---|---|
[data-scope] | carousel |
[data-part] | next-trigger |
[data-orientation] | The orientation of the nexttrigger |
PrevTrigger
| Prop | Default | Type |
|---|---|---|
asChild | booleanUse the provided child element as the default rendered element, combining their props and behavior. For more details, read our Composition guide. |
| Data Attribute | Value |
|---|---|
[data-scope] | carousel |
[data-part] | prev-trigger |
[data-orientation] | The orientation of the prevtrigger |
RootProvider
| Prop | Default | Type |
|---|---|---|
value | UseCarouselReturn | |
asChild | booleanUse the provided child element as the default rendered element, combining their props and behavior. For more details, read our Composition guide. |
Accessibility
Complies with the Carousel WAI-ARIA design pattern.