Carousel

A row of slides shown one or a few at a time, moved by swipes, previous and next buttons or dots, with optional autoplay.
Stable
Web
iOS
Android
@advui/core
Source

Basic

Installation

pnpm
pnpm add @advui/core
npm
npm install @advui/core

Usage

import { Card, Carousel } from '@advui/core'

<Carousel aria-label="Featured articles" slidesPerView={{ base: 1, md: 3 }}>
  {articles.map((article) => (
    <Card key={article.id} flexGrow={1}>…</Card>
  ))}
</Carousel>

Examples

Several per view

A part of the next card on phones, two from `sm` and three from `md`.

Photos

Images with captions; `loop` goes from the last photo back to the first.

Autoplay

Moves every 6 seconds and waits while the pointer or focus is on it. It starts paused for users who ask for less motion.

Controlled

An onboarding tour whose own buttons set `index`; the dots stay in step.

API reference

Carousel

Each child is a slide; children that are not `Carousel.Item` are wrapped in one. Style and layout props go to the outer box.
PropTypeDefaultDescription
aria-labelstring—Names the carousel, e.g. "Featured articles". Recommended.
indexnumber—The slide first in view, when you control it.
defaultIndexnumber0Starting `index` when uncontrolled.
onIndexChange(index: number) => void—Called with the new `index` after a button, dot, key, swipe or autoplay.
slidesPerViewnumberor a breakpoint map1Slides in view at once, mobile first. A fraction such as 1.2 shows part of the next slide.
gapSpaceTokens'4'Space between slides.
loopbooleanfalseNext on the last slide goes back to the first, and Previous on the first goes to the last.
autoplayboolean | numberfalseMoves to the next slide on its own, back to the first after the last: `true` every 5 seconds, or a delay in milliseconds. Adds a pause button.
showArrowsbooleantruePrevious and next buttons, disabled at the ends unless `loop`.
showDotsbooleantrueA dot for each slide that can come first, which jumps to it.
labelsPartial<CarouselLabels>—Button names (`previous`, `next`, `goTo(index)`, `current`, `play`, `pause`), the announcement (`position(index, count)`) and the web role descriptions and slide names (`carousel`, `slide`, `slideName(index, count)`), for translation.

Carousel.Item

One slide, for slide props such as padding or a background. Carousel sets its width; slides in a row share the tallest one’s height.

Accessibility

  • On web the carousel is a region named by aria-label and described as a “carousel”; each slide is a group named “2 of 5” and described as a “slide” (WAI-ARIA APG carousel pattern).
  • Previous, next and the dots are buttons with names (“Next slide”, “Go to slide 3”); the current dot has aria-current on web, and on iOS and Android says “current” in its name (a selected state that moves makes TalkBack read every dot).
  • The controls come before the slides in focus and reading order, so the pause button is met before the slides move; they show under the slides.
  • After a button, dot, key or swipe the new position (“Slide 3 of 5”) is announced: through a polite live region on web, with AccessibilityInfo.announceForAccessibility on iOS and Android. Autoplay moves are not announced.
  • Autoplay waits while the pointer is over the carousel, focus is inside it or a finger is on it, and starts paused when the user asks for less motion. The pause button stops it (WCAG 2.2.2).
  • Slides out of view stay in the tree, so screen readers can read them; on web, tabbing to a link in one scrolls it into view and updates the dots.
Keyboard interactions
KeyAction
TabMoves through the controls, then the slides.
Arrow Left / Arrow RightPrevious or next slide, while the slide area has focus (web).
Home / EndFirst or last slide, while the slide area has focus (web).
Enter / SpacePresses the focused button or dot.

Responsive behavior

slidesPerView takes a mobile-first map; on web the slide widths are CSS media queries, so the server renders them right. The number of dots follows the current breakpoint after hydration.

Platform notes

Web
CSS scroll snap: touch, trackpads and the scroll wheel move it, one slide per swipe. A mouse drag does not; the arrows and dots do. The scrollbar is hidden.
iOS
A horizontal ScrollView that snaps to each slide, one per swipe. Slide widths come from its measured width, so they follow rotation.
Android
Same as iOS. It swipes sideways inside a vertically scrolling screen (nestedScrollEnabled).
Since v0.14.0Last updated Nov 2, 2026Edit this page on GitHub