Get StartedComponentsStylingThemingMath & Science
MCP

Basics

Carousel

Cycles through a series of slides inside a container. The indicators are small neutral dots and the active one uses the solid color of the palette.

Slides scroll and snap with native CSS scroll snapping, so touch swiping works out of the box. Every part is optional: compose only the arrows, indicators, autoplay button or progress text you need.

Markdown

Import

tsx
import { Carousel } from "@indoku/ui"

Anatomy

Carousel.Root (slideCount)├─ Carousel.ItemGroup│  └─ Carousel.Item (index)└─ Carousel.Control   ├─ Carousel.PrevTrigger / Carousel.NextTrigger   ├─ Carousel.Indicators            shortcut for the group below   │  = Carousel.IndicatorGroup > Carousel.Indicator (index)   ├─ Carousel.AutoplayTrigger > Carousel.AutoplayIndicator   └─ Carousel.ProgressText

Examples

Basic

slideCount is required: the carousel needs it to compute snap points during server rendering. Give every Carousel.Item its index.

Floating arrows

Put the triggers inside Carousel.Control next to the item group. Here they sit on top of the slide with absolute positioning.

Controlled

Use page and onPageChange to read and set the active slide from your own state.

Slide 1 of 5

Store

useCarousel returns a store you pass to Carousel.RootProvider. Call scrollTo, scrollNext and friends from anywhere, even outside the carousel.

Thumbnail indicators

Render Carousel.IndicatorGroup yourself and pass children to each Carousel.Indicator. Add unstyled to drop the dot styling, and style the active one with _current.

Multiple slides per page

slidesPerPage shows several slides at once and spacing sets the gap between them. Next and previous move one page at a time unless you set slidesPerMove.

Variable size

Add autoSize so each slide keeps its own width, and set width="auto" on the item. snapAlign controls where a slide stops.

Vertical

Set orientation="vertical" and give the root a height. The arrows and indicators stack vertically too.

Loop and mouse drag

loop wraps from the last slide to the first. allowMouseDrag lets desktop users drag, touch devices always can.

Drag with the mouse, or keep pressing next: it wraps around.

Autoplay

Pass autoplay (4 seconds by default) or { delay } in milliseconds. Carousel.AutoplayTrigger pauses and resumes it, and Carousel.ProgressText shows 1 / 5.

1 / 5

Compose the carousel with a Dialog for a gallery that opens on click.

Props

Root

PropTypeDefaultDescription
slideCount*number–Total number of slides. Needed for SSR so snap points exist on the first render.
pagenumber–The active page, for controlled usage.
defaultPagenumber0The initial page when uncontrolled.
onPageChange(details: { page: number }) => void–Called when the page changes.
slidesPerPagenumber1How many slides are visible at once. Decimals such as 1.5 show a peek of the next slide.
slidesPerMovenumber | 'auto''auto'How many slides one move scrolls. auto follows slidesPerPage.
spacingstring'1rem'Space between slides.
orientation'horizontal' | 'vertical''horizontal'Scroll direction.
loopbooleanfalseWrap around at both ends.
autoplayboolean | { delay: number }falseScroll automatically. The default delay is 4000 ms.
autoSizebooleanfalseAllow slides with different widths or heights.
allowMouseDragbooleanfalseAllow scrolling by dragging with the mouse.
snapType'proximity' | 'mandatory''mandatory'How strictly scrolling snaps to slides.
inViewThresholdnumber | number[]0.6How much of a slide must be visible to count as in view.
paddingstring–Extra space around the scroll area, so neighbouring slides stay partly visible.
onAutoplayStatusChange(details) => void–Called when autoplay starts or stops.
onDragStatusChange(details) => void–Called when dragging starts or stops.
translationsIntlTranslations–Localized labels used for accessibility.
idsPartial<{ root, item, itemGroup, ... }>–Custom element ids, useful for composition.
asChildboolean–Render the child element instead of the default one.
unstyledboolean–Remove the component's styles.

Item

PropTypeDefaultDescription
index*number–The position of this slide.
snapAlign'start' | 'center' | 'end''start'Where the slide stops when snapping.

Indicator

PropTypeDefaultDescription
index*number–The slide this indicator jumps to.
unstyledboolean–Remove the dot styling, to render your own content such as a thumbnail.

* required. Style props and HTML attributes are accepted as well.

Accessibility

  • The root is exposed as a carousel region and each slide as a slide group, so screen readers announce the position (for example 1 of 5).
  • Icon-only triggers have no text. Always give Carousel.PrevTrigger and Carousel.NextTrigger buttons an aria-label.
  • Autoplay moves content on its own. Offer Carousel.AutoplayTrigger so people can pause it, and avoid autoplay for anything important.

Notes

  • In Carousel.AutoplayIndicator, paused is what shows while the carousel is playing (the button will pause it) and play shows while it is paused.
  • Slides use CSS scroll snapping, not transforms. Anything that scrolls natively (trackpad, touch, keyboard) works with it.
  • Carousel.Indicators is a shortcut. Use Carousel.IndicatorGroup plus Carousel.Indicator when each indicator needs custom content.
  • Images inside slides should set draggable={false} when allowMouseDrag is on, otherwise the browser starts an image drag.

Created by @indokudev