# Carousel

URL: https://ark-ui.com/docs/components/carousel
Source: https://raw.githubusercontent.com/chakra-ui/ark/refs/heads/main/website/src/content/pages/components/carousel.mdx

An interactive slideshow component for cycling through elements.

---

<ComponentPreview id="Carousel" />

## Anatomy

<Anatomy id="carousel" />

```tsx
<Carousel.Root>
  <Carousel.Control>
    <Carousel.PrevTrigger />
    <Carousel.NextTrigger />
  </Carousel.Control>
  <Carousel.ItemGroup>
    <Carousel.Item />
  </Carousel.ItemGroup>
  <Carousel.IndicatorGroup>
    <Carousel.Indicator />
  </Carousel.IndicatorGroup>
</Carousel.Root>
```

## Examples

**Example: basic**

```ripple
import { Carousel } from 'ark-ripple/carousel';
import styles from 'styles/carousel.module.css';

const images = [
  { src: 'https://picsum.photos/seed/1/500/300', alt: 'Nature landscape', index: 0 },
  { src: 'https://picsum.photos/seed/2/500/300', alt: 'City skyline', index: 1 },
  { src: 'https://picsum.photos/seed/3/500/300', alt: 'Mountain view', index: 2 },
  { src: 'https://picsum.photos/seed/4/500/300', alt: 'Ocean sunset', index: 3 },
  { src: 'https://picsum.photos/seed/5/500/300', alt: 'Forest path', index: 4 },
];

export component Basic() {
  <Carousel.Root class={styles.Root} slideCount={images.length}>
    <Carousel.Control class={styles.Control}>
      <Carousel.PrevTrigger class={styles.Trigger}>{'←'}</Carousel.PrevTrigger>
      <Carousel.ItemGroup class={styles.ItemGroup}>
        for (const image of images; key image.index) {
          <Carousel.Item class={styles.Item} index={image.index}>
            <img src={image.src} alt={image.alt} width="500" height="300" />
          </Carousel.Item>
        }
      </Carousel.ItemGroup>
      <Carousel.NextTrigger class={styles.Trigger}>{'→'}</Carousel.NextTrigger>
    </Carousel.Control>
    <Carousel.IndicatorGroup class={styles.IndicatorGroup}>
      for (const image of images; key image.index) {
        <Carousel.Indicator class={styles.Indicator} index={image.index} />
      }
    </Carousel.IndicatorGroup>
  </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:

**Example: controlled**

```ripple
import { Carousel } from 'ark-ripple/carousel';
import { track } from 'ripple';
import styles from 'styles/carousel.module.css';

const images = [
  { src: 'https://picsum.photos/seed/1/500/300', alt: 'Nature landscape', index: 0 },
  { src: 'https://picsum.photos/seed/2/500/300', alt: 'City skyline', index: 1 },
  { src: 'https://picsum.photos/seed/3/500/300', alt: 'Mountain view', index: 2 },
  { src: 'https://picsum.photos/seed/4/500/300', alt: 'Ocean sunset', index: 3 },
  { src: 'https://picsum.photos/seed/5/500/300', alt: 'Forest path', index: 4 },
];

export component Controlled() {
  let page = track(0);

  <Carousel.Root
    class={styles.Root}
    slideCount={images.length}
    {page}
    onPageChange={(e) => {
      @page = e.page;
    }}
  >
    <Carousel.Control class={styles.Control}>
      <Carousel.PrevTrigger class={styles.Trigger}>{'←'}</Carousel.PrevTrigger>
      <Carousel.ItemGroup class={styles.ItemGroup}>
        for (const image of images; key image.index) {
          <Carousel.Item class={styles.Item} index={image.index}>
            <img src={image.src} alt={image.alt} width="500" height="300" />
          </Carousel.Item>
        }
      </Carousel.ItemGroup>
      <Carousel.NextTrigger class={styles.Trigger}>{'→'}</Carousel.NextTrigger>
    </Carousel.Control>
    <Carousel.IndicatorGroup class={styles.IndicatorGroup}>
      for (const image of images; key image.index) {
        <Carousel.Indicator class={styles.Indicator} index={image.index} />
      }
    </Carousel.IndicatorGroup>
  </Carousel.Root>
}

```

### Root Provider

An alternative way to control the carousel is to use the `RootProvider` component and the `useCarousel` hook. This way
you can access the state and methods from outside the component.

**Example: root-provider**

```ripple
import { Carousel } from 'ark-ripple/carousel';
import { useCarousel } from 'ark-ripple/carousel';
import styles from 'styles/carousel.module.css';

const images = [
  { src: 'https://picsum.photos/seed/1/500/300', alt: 'Nature landscape', index: 0 },
  { src: 'https://picsum.photos/seed/2/500/300', alt: 'City skyline', index: 1 },
  { src: 'https://picsum.photos/seed/3/500/300', alt: 'Mountain view', index: 2 },
  { src: 'https://picsum.photos/seed/4/500/300', alt: 'Ocean sunset', index: 3 },
  { src: 'https://picsum.photos/seed/5/500/300', alt: 'Forest path', index: 4 },
];

export component RootProvider() {
  const carousel = useCarousel({ slideCount: images.length });

  <div class="vstack">
    <output>
      {'Page: '}
      {@carousel.page}
    </output>
    <Carousel.RootProvider value={carousel} class={styles.Root}>
      <Carousel.Control class={styles.Control}>
        <Carousel.PrevTrigger class={styles.Trigger}>{'←'}</Carousel.PrevTrigger>
        <Carousel.ItemGroup class={styles.ItemGroup}>
          for (const image of images; key image.index) {
            <Carousel.Item class={styles.Item} index={image.index}>
              <img src={image.src} alt={image.alt} width="500" height="300" />
            </Carousel.Item>
          }
        </Carousel.ItemGroup>
        <Carousel.NextTrigger class={styles.Trigger}>{'→'}</Carousel.NextTrigger>
      </Carousel.Control>
      <Carousel.IndicatorGroup class={styles.IndicatorGroup}>
        for (const image of images; key image.index) {
          <Carousel.Indicator class={styles.Indicator} index={image.index} />
        }
      </Carousel.IndicatorGroup>
    </Carousel.RootProvider>
  </div>
}

```

### Autoplay

Pass the `autoplay` and `loop` props to `Carousel.Root` to make the carousel play automatically.

**Example: autoplay**

```ripple
import { Carousel } from 'ark-ripple/carousel';
import styles from 'styles/carousel.module.css';

const images = [
  { src: 'https://picsum.photos/seed/1/500/300', alt: 'Nature landscape', index: 0 },
  { src: 'https://picsum.photos/seed/2/500/300', alt: 'City skyline', index: 1 },
  { src: 'https://picsum.photos/seed/3/500/300', alt: 'Mountain view', index: 2 },
  { src: 'https://picsum.photos/seed/4/500/300', alt: 'Ocean sunset', index: 3 },
  { src: 'https://picsum.photos/seed/5/500/300', alt: 'Forest path', index: 4 },
];

export component Autoplay() {
  <Carousel.Root class={styles.Root} slideCount={images.length} autoplay loop>
    <Carousel.ItemGroup class={styles.ItemGroup}>
      for (const image of images; key image.index) {
        <Carousel.Item class={styles.Item} index={image.index}>
          <img src={image.src} alt={image.alt} width="500" height="300" />
        </Carousel.Item>
      }
    </Carousel.ItemGroup>
    <Carousel.Control class={styles.Control}>
      <Carousel.PrevTrigger class={styles.Trigger}>{'‹'}</Carousel.PrevTrigger>
      <Carousel.AutoplayTrigger class={styles.AutoplayTrigger}>
        <Carousel.AutoplayIndicator fallback="▶">{'⏸'}</Carousel.AutoplayIndicator>
      </Carousel.AutoplayTrigger>
      <Carousel.NextTrigger class={styles.Trigger}>{'›'}</Carousel.NextTrigger>
    </Carousel.Control>
  </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.

**Example: pause-on-hover**

```ripple
import { Carousel } from 'ark-ripple/carousel';
import styles from 'styles/carousel.module.css';

const images = [
  { src: 'https://picsum.photos/seed/1/500/300', alt: 'Nature landscape', index: 0 },
  { src: 'https://picsum.photos/seed/2/500/300', alt: 'City skyline', index: 1 },
  { src: 'https://picsum.photos/seed/3/500/300', alt: 'Mountain view', index: 2 },
  { src: 'https://picsum.photos/seed/4/500/300', alt: 'Ocean sunset', index: 3 },
  { src: 'https://picsum.photos/seed/5/500/300', alt: 'Forest path', index: 4 },
];

export component PauseOnHover() {
  <Carousel.Root class={styles.Root} slideCount={images.length} autoplay loop>
    <Carousel.Control class={styles.Control}>
      <Carousel.Context>
        component children({ context }) {
          <span class={styles.StatusText}>
            {'Autoplay is: '}
            {@context.isPlaying ? 'playing' : 'paused'}
          </span>
        }
      </Carousel.Context>
    </Carousel.Control>
    <Carousel.Context>
      component children({ context }) {
        <Carousel.ItemGroup
          class={styles.ItemGroup}
          onPointerOver={() => {
            @context.pause();
          }}
          onPointerLeave={() => {
            @context.play();
          }}
        >
          for (const image of images; key image.index) {
            <Carousel.Item class={styles.Item} index={image.index}>
              <img src={image.src} alt={image.alt} width="500" height="300" />
            </Carousel.Item>
          }
        </Carousel.ItemGroup>
      }
    </Carousel.Context>
    <Carousel.IndicatorGroup class={styles.IndicatorGroup}>
      for (const image of images; key image.index) {
        <Carousel.Indicator class={styles.Indicator} index={image.index} />
      }
    </Carousel.IndicatorGroup>
  </Carousel.Root>
}

```

### Thumbnail Indicators

Replace default indicator dots with image thumbnails. Render each thumbnail inside `Carousel.Indicator` to create a
visual preview of each slide:

**Example: thumbnail-indicator**

```ripple
import { Carousel } from 'ark-ripple/carousel';
import styles from 'styles/carousel.module.css';

const images = [
  { src: 'https://picsum.photos/seed/1/500/300', alt: 'Nature landscape', index: 0 },
  { src: 'https://picsum.photos/seed/2/500/300', alt: 'City skyline', index: 1 },
  { src: 'https://picsum.photos/seed/3/500/300', alt: 'Mountain view', index: 2 },
  { src: 'https://picsum.photos/seed/4/500/300', alt: 'Ocean sunset', index: 3 },
  { src: 'https://picsum.photos/seed/5/500/300', alt: 'Forest path', index: 4 },
];

export component ThumbnailIndicator() {
  <Carousel.Root class={styles.Root} defaultPage={0} slideCount={images.length}>
    <Carousel.Control class={styles.Control}>
      <Carousel.PrevTrigger class={styles.Trigger}>{'←'}</Carousel.PrevTrigger>
      <Carousel.ItemGroup class={styles.ItemGroup}>
        for (const image of images; key image.index) {
          <Carousel.Item class={styles.Item} index={image.index}>
            <img src={image.src} alt={image.alt} width="500" height="300" />
          </Carousel.Item>
        }
      </Carousel.ItemGroup>
      <Carousel.NextTrigger class={styles.Trigger}>{'→'}</Carousel.NextTrigger>
    </Carousel.Control>
    <Carousel.IndicatorGroup class={styles.IndicatorGroup}>
      for (const image of images; key image.index) {
        <Carousel.Indicator class={styles.ThumbnailIndicator} index={image.index}>
          <img src={image.src} alt={image.alt} width="500" height="300" />
        </Carousel.Indicator>
      }
    </Carousel.IndicatorGroup>
  </Carousel.Root>
}

```

### Vertical

Add the `orientation="vertical"` prop to `Carousel.Root` to switch the carousel to vertical scrolling. This can be
helpful for displaying vertical galleries or content feeds.

**Example: vertical**

```ripple
import { Carousel } from 'ark-ripple/carousel';
import styles from 'styles/carousel.module.css';

const images = [
  { src: 'https://picsum.photos/seed/1/500/300', alt: 'Nature landscape', index: 0 },
  { src: 'https://picsum.photos/seed/2/500/300', alt: 'City skyline', index: 1 },
  { src: 'https://picsum.photos/seed/3/500/300', alt: 'Mountain view', index: 2 },
  { src: 'https://picsum.photos/seed/4/500/300', alt: 'Ocean sunset', index: 3 },
  { src: 'https://picsum.photos/seed/5/500/300', alt: 'Forest path', index: 4 },
];

export component Vertical() {
  <Carousel.Root
    class={styles.Root}
    defaultPage={0}
    orientation="vertical"
    slideCount={images.length}
  >
    <Carousel.ItemGroup class={styles.ItemGroup}>
      for (const image of images; key image.index) {
        <Carousel.Item class={styles.Item} index={image.index}>
          <img src={image.src} alt={image.alt} width="500" height="300" />
        </Carousel.Item>
      }
    </Carousel.ItemGroup>
    <Carousel.Control class={styles.Control}>
      <Carousel.PrevTrigger class={styles.Trigger}>{'↑'}</Carousel.PrevTrigger>
      <Carousel.IndicatorGroup class={styles.IndicatorGroup}>
        for (const image of images; key image.index) {
          <Carousel.Indicator class={styles.Indicator} index={image.index} />
        }
      </Carousel.IndicatorGroup>
      <Carousel.NextTrigger class={styles.Trigger}>{'↓'}</Carousel.NextTrigger>
    </Carousel.Control>
  </Carousel.Root>
}

```

### Dynamic

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.

**Example: dynamic-slides**

```ripple
import { Carousel } from 'ark-ripple/carousel';
import { track } from 'ripple';
import button from 'styles/button.module.css';
import styles from 'styles/carousel.module.css';

export component DynamicSlides() {
  let slides = track([0, 1, 2, 3, 4]);
  let page = track(0);

  <div class="stack">
    <Carousel.Root
      class={styles.Root}
      slideCount={@slides.length}
      {page}
      onPageChange={(e) => {
        @page = e.page;
      }}
    >
      <Carousel.ItemGroup class={styles.ItemGroup}>
        for (const index of @slides; key index) {
          <Carousel.Item class={styles.Item} {index}>
            <div class={styles.Slide}>
              {'Slide '}
              {index + 1}
            </div>
          </Carousel.Item>
        }
      </Carousel.ItemGroup>
      <Carousel.Control class={styles.Control}>
        <Carousel.PrevTrigger class={styles.Trigger}>{'←'}</Carousel.PrevTrigger>
        <Carousel.IndicatorGroup class={styles.IndicatorGroup}>
          for (const index of @slides; key index) {
            <Carousel.Indicator class={styles.Indicator} {index} />
          }
        </Carousel.IndicatorGroup>
        <Carousel.NextTrigger class={styles.Trigger}>{'→'}</Carousel.NextTrigger>
      </Carousel.Control>
    </Carousel.Root>
    <button
      class={button.Root}
      onClick={() => {
        @slides = [...@slides, @slides.length];
      }}
    >
      {'+ 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.

**Example: scroll-to**

```ripple
import { Carousel } from 'ark-ripple/carousel';
import button from 'styles/button.module.css';
import styles from 'styles/carousel.module.css';

const slides = [0, 1, 2, 3, 4];

export component ScrollTo() {
  <Carousel.Root class={styles.Root} slideCount={slides.length}>
    <Carousel.Context>
      component children({ context }) {
        <button
          class={button.Root}
          onClick={() => {
            @context.scrollToIndex(3);
          }}
        >
          {'Go to slide 4'}
        </button>
      }
    </Carousel.Context>
    <Carousel.ItemGroup class={styles.ItemGroup}>
      for (const index of slides; key index) {
        <Carousel.Item class={styles.Item} {index}>
          <div class={styles.Slide}>
            {'Slide '}
            {index + 1}
          </div>
        </Carousel.Item>
      }
    </Carousel.ItemGroup>
    <Carousel.Control class={styles.Control}>
      <Carousel.PrevTrigger class={styles.Trigger}>{'←'}</Carousel.PrevTrigger>
      <Carousel.NextTrigger class={styles.Trigger}>{'→'}</Carousel.NextTrigger>
    </Carousel.Control>
    <Carousel.IndicatorGroup class={styles.IndicatorGroup}>
      for (const index of slides; key index) {
        <Carousel.Indicator class={styles.Indicator} {index} />
      }
    </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.

**Example: slides-per-page**

```ripple
import { Carousel } from 'ark-ripple/carousel';
import styles from 'styles/carousel.module.css';

const slides = [0, 1, 2, 3, 4, 5];
const pageIndicators = [0, 1, 2];

export component SlidesPerPage() {
  <Carousel.Root class={styles.Root} slideCount={slides.length} slidesPerPage={2} spacing="20px">
    <Carousel.Control class={styles.Control}>
      <Carousel.PrevTrigger class={styles.Trigger}>{'←'}</Carousel.PrevTrigger>
      <Carousel.NextTrigger class={styles.Trigger}>{'→'}</Carousel.NextTrigger>
    </Carousel.Control>
    <Carousel.ItemGroup class={styles.ItemGroup}>
      for (const index of slides; key index) {
        <Carousel.Item class={styles.Item} {index}>
          <div class={styles.Slide}>
            {'Slide '}
            {index + 1}
          </div>
        </Carousel.Item>
      }
    </Carousel.ItemGroup>
    <Carousel.IndicatorGroup class={styles.IndicatorGroup}>
      for (const index of pageIndicators; key index) {
        <Carousel.Indicator class={styles.Indicator} {index} />
      }
    </Carousel.IndicatorGroup>
  </Carousel.Root>
}

```

### Spacing

Control the gap between slides using the `spacing` prop on `Carousel.Root`. Combine it with `slidesPerPage` to create
layouts that show partial previews of adjacent slides.

**Example: spacing**

```ripple
import { Carousel } from 'ark-ripple/carousel';
import styles from 'styles/carousel.module.css';

const slides = [0, 1, 2, 3, 4, 5];

export component Spacing() {
  <Carousel.Root class={styles.Root} slideCount={slides.length} slidesPerPage={1.5} spacing="48px">
    <span class={styles.StatusText}>{'spacing=\'48px\''}</span>
    <Carousel.ItemGroup class={styles.ItemGroup}>
      for (const index of slides; key index) {
        <Carousel.Item class={styles.Item} {index}>
          <div class={styles.Slide}>{index + 1}</div>
        </Carousel.Item>
      }
    </Carousel.ItemGroup>
    <Carousel.Control class={styles.Control}>
      <Carousel.PrevTrigger class={styles.Trigger}>{'←'}</Carousel.PrevTrigger>
      <Carousel.Context>
        component children({ context }) {
          <Carousel.IndicatorGroup class={styles.IndicatorGroup}>
            for (const snapPoint of @context.pageSnapPoints; key snapPoint) {
              <Carousel.Indicator
                class={styles.Indicator}
                index={@context.pageSnapPoints.indexOf(snapPoint)}
              />
            }
          </Carousel.IndicatorGroup>
        }
      </Carousel.Context>
      <Carousel.NextTrigger class={styles.Trigger}>{'→'}</Carousel.NextTrigger>
    </Carousel.Control>
  </Carousel.Root>
}

```

### Variable Sizes

To allow slides with different widths, set the `autoSize` prop on `Carousel.Root`. This lets each `Carousel.Item` define
its own width, and the carousel will adjust automatically. You can also use the `snapAlign` prop on individual items to
control where each one snaps into view.

**Example: variable-size**

```ripple
import { Carousel } from 'ark-ripple/carousel';
import styles from 'styles/carousel.module.css';

const items = [
  { id: '1', width: '120px', label: 'Small', index: 0 },
  { id: '2', width: '200px', label: 'Medium Size', index: 1 },
  { id: '3', width: '80px', label: 'XS', index: 2 },
  { id: '4', width: '250px', label: 'Large Content Here', index: 3 },
  { id: '5', width: '150px', label: 'Regular', index: 4 },
];

export component VariableSize() {
  <Carousel.Root class={styles.Root} slideCount={items.length} autoSize spacing="8px">
    <Carousel.Control class={styles.Control}>
      <Carousel.PrevTrigger class={styles.Trigger}>{'←'}</Carousel.PrevTrigger>
      <Carousel.NextTrigger class={styles.Trigger}>{'→'}</Carousel.NextTrigger>
    </Carousel.Control>
    <Carousel.ItemGroup class={styles.ItemGroup}>
      for (const item of items; key item.id) {
        <Carousel.Item index={item.index} snapAlign="center">
          <div class={styles.Slide} style={{ width: item.width, height: '6rem' }}>{item.label}</div>
        </Carousel.Item>
      }
    </Carousel.ItemGroup>
    <Carousel.Context>
      component children({ context }) {
        <Carousel.IndicatorGroup class={styles.IndicatorGroup}>
          for (const snapPoint of @context.pageSnapPoints; key snapPoint) {
            <Carousel.Indicator
              class={styles.Indicator}
              index={@context.pageSnapPoints.indexOf(snapPoint)}
            />
          }
        </Carousel.IndicatorGroup>
      }
    </Carousel.Context>
  </Carousel.Root>
}

```

## API Reference

### Props

**Component API Reference**

**Root Props:**

| Prop | Type | Required | Description |
|------|------|----------|-------------|
| `slideCount` | `number` | Yes | The total number of slides.
Useful for SSR to render the initial ating the snap points. |
| `allowMouseDrag` | `boolean` | No | Whether to allow scrolling via dragging with mouse |
| `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. |
| `autoplay` | `boolean | { delay: number }` | No | Whether to scroll automatically. The default delay is 4000ms. |
| `autoSize` | `boolean` | No | Whether to enable variable width slides. |
| `defaultPage` | `number` | No | 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
}>` | No | The ids of the elements in the carousel. Useful for composition. |
| `inViewThreshold` | `number | number[]` | No | The threshold for determining if an item is in view. |
| `loop` | `boolean` | No | Whether the carousel should loop around. |
| `onAutoplayStatusChange` | `(details: AutoplayStatusDetails) => void` | No | Function called when the autoplay status changes. |
| `onDragStatusChange` | `(details: DragStatusDetails) => void` | No | Function called when the drag status changes. |
| `onPageChange` | `(details: PageChangeDetails) => void` | No | Function called when the page changes. |
| `orientation` | `'horizontal' | 'vertical'` | No | The orientation of the element. |
| `padding` | `string` | No | Defines the extra space added around the scrollable area,
enabling nearby items to remain partially in view. |
| `page` | `number` | No | The controlled page of the carousel. |
| `slidesPerMove` | `number | 'auto'` | No | 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` | `number` | No | The number of slides to show at a time. |
| `snapType` | `'proximity' | 'mandatory'` | No | The snap type of the item. |
| `spacing` | `string` | No | The amount of space between items. |
| `translations` | `IntlTranslations` | No | The localized messages to use. |


**Root Data Attributes:**

| Attribute | Value |
|-----------|-------|
| `[data-scope]` | carousel |
| `[data-part]` | root |
| `[data-orientation]` | The orientation of the carousel |


**Root CSS Variables:**

| 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 |


**AutoplayIndicator Props:**

| Prop | Type | Required | Description |
|------|------|----------|-------------|
| `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. |
| `fallback` | `string | number | bigint | boolean | ReactElement<unknown, string | JSXElementConstructor<any>> | Iterable<ReactNode> | ReactPortal | Promise<...>` | No | The fallback content to render when autoplay is paused. |


**AutoplayTrigger Props:**

| Prop | Type | Required | Description |
|------|------|----------|-------------|
| `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. |


**AutoplayTrigger Data Attributes:**

| Attribute | Value |
|-----------|-------|
| `[data-scope]` | carousel |
| `[data-part]` | autoplay-trigger |
| `[data-orientation]` | The orientation of the autoplaytrigger |
| `[data-pressed]` | Present when pressed |


**Control Props:**

| Prop | Type | Required | Description |
|------|------|----------|-------------|
| `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. |


**Control Data Attributes:**

| Attribute | Value |
|-----------|-------|
| `[data-scope]` | carousel |
| `[data-part]` | control |
| `[data-orientation]` | The orientation of the control |


**IndicatorGroup Props:**

| Prop | Type | Required | Description |
|------|------|----------|-------------|
| `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. |


**IndicatorGroup Data Attributes:**

| Attribute | Value |
|-----------|-------|
| `[data-scope]` | carousel |
| `[data-part]` | indicator-group |
| `[data-orientation]` | The orientation of the indicatorgroup |


**Indicator Props:**

| Prop | Type | Required | Description |
|------|------|----------|-------------|
| `index` | `number` | Yes | The index of the indicator. |
| `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. |
| `readOnly` | `boolean` | No | Whether the indicator is read only. |


**Indicator Data Attributes:**

| 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 Props:**

| Prop | Type | Required | Description |
|------|------|----------|-------------|
| `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. |


**ItemGroup Data Attributes:**

| 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 Props:**

| Prop | Type | Required | Description |
|------|------|----------|-------------|
| `index` | `number` | Yes | The index of the item. |
| `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. |
| `snapAlign` | `'center' | 'start' | 'end'` | No | The snap alignment of the item. |


**Item Data Attributes:**

| 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 Props:**

| Prop | Type | Required | Description |
|------|------|----------|-------------|
| `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. |


**NextTrigger Data Attributes:**

| Attribute | Value |
|-----------|-------|
| `[data-scope]` | carousel |
| `[data-part]` | next-trigger |
| `[data-orientation]` | The orientation of the nexttrigger |


**PrevTrigger Props:**

| Prop | Type | Required | Description |
|------|------|----------|-------------|
| `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. |


**PrevTrigger Data Attributes:**

| Attribute | Value |
|-----------|-------|
| `[data-scope]` | carousel |
| `[data-part]` | prev-trigger |
| `[data-orientation]` | The orientation of the prevtrigger |


**ProgressText Props:**

| Prop | Type | Required | Description |
|------|------|----------|-------------|
| `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. |


**RootProvider Props:**

| Prop | Type | Required | Description |
|------|------|----------|-------------|
| `value` | `UseCarouselReturn` | Yes |  |
| `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. |


### Context

**API:**

| Property | Type | Description |
|----------|------|-------------|
| `page` | `number` | The current index of the carousel |
| `pageSnapPoints` | `number[]` | The current snap points of the carousel |
| `isPlaying` | `boolean` | Whether the carousel is auto playing |
| `isDragging` | `boolean` | Whether the carousel is being dragged. This only works when `draggable` is true. |
| `canScrollNext` | `boolean` | Whether the carousel is can scroll to the next view |
| `canScrollPrev` | `boolean` | Whether the carousel is can scroll to the previous view |
| `scrollToIndex` | `(index: number, instant?: boolean) => void` | Function to scroll to a specific item index |
| `scrollTo` | `(page: number, instant?: boolean) => void` | Function to scroll to a specific page |
| `scrollNext` | `(instant?: boolean) => void` | Function to scroll to the next page |
| `scrollPrev` | `(instant?: boolean) => void` | Function to scroll to the previous page |
| `getProgress` | `() => number` | Returns the current scroll progress as a percentage |
| `getProgressText` | `() => string` | Returns the progress text |
| `play` | `VoidFunction` | Function to start/resume autoplay |
| `pause` | `VoidFunction` | Function to pause autoplay |
| `isInView` | `(index: number) => boolean` | Whether the item is in view |
| `refresh` | `VoidFunction` | Function to re-compute the snap points
and clamp the page |


## Accessibility

Complies with the [Carousel WAI-ARIA design pattern](https://www.w3.org/WAI/ARIA/apg/patterns/carousel/).