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-part
attribute 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.RootProvider
component, you don't need to use theCarousel.Root
component.
Autoplay
Pass the autoplay
and loop
props to Carousel.Root
to make the carousel play automatically.
Note: Adding
loop
ensures 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 | number The total number of slides. Useful for SSR to render the initial ating the snap points. | |
allowMouseDrag | false | boolean Whether to allow scrolling via dragging with mouse |
asChild | boolean Use 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 | number The 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 | boolean Whether the carousel should loop around. |
onAutoplayStatusChange | (details: AutoplayStatusDetails) => void Function called when the autoplay status changes. | |
onDragStatusChange | (details: DragStatusDetails) => void Function called when the drag status changes. | |
onPageChange | (details: PageChangeDetails) => void Function called when the page changes. | |
orientation | 'horizontal' | 'horizontal' | 'vertical' The orientation of the element. |
padding | string Defines the extra space added around the scrollable area, enabling nearby items to remain partially in view. | |
page | number The 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 | number The number of slides to show at a time. |
snapType | 'mandatory' | 'proximity' | 'mandatory' The snap type of the item. |
spacing | '0px' | string The amount of space between items. |
translations | IntlTranslations The 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 | boolean Use 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 | boolean Use 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 | boolean Use 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 | number The index of the indicator. | |
asChild | boolean Use the provided child element as the default rendered element, combining their props and behavior. For more details, read our Composition guide. | |
readOnly | false | boolean Whether 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 | boolean Use 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 | number The index of the item. | |
asChild | boolean Use 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 | boolean Use 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 | boolean Use 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 | boolean Use 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.