vaiperui

components / carousel

Carousel

Slides with arrows, dots, keyboard, optional autoplay and loop.

How to use

Each child is a slide. It is a `region` with `aria-roledescription="carousel"`; slides are `group`s and the ones out of view are hidden from assistive tech and not focusable. ←/→/Home/End navigate. `autoplay` pauses on hover and focus and never runs with `prefers-reduced-motion`. `index` can be controlled; `slidesPerView` shows several slides at once.

preview
Slide 1
Carousel.tsx
import { Carousel } from "vaiperui";
<Carousel aria-label="Featured slides" loop autoplay={4000}>
<img src="/photos/1.jpg" alt="One" />
<img src="/photos/2.jpg" alt="Two" />
<img src="/photos/3.jpg" alt="Three" />
</Carousel>

Several per view

preview
Slide 1
Slide 2
slidesPerView={2}
per-view.tsx
<Carousel aria-label="..." slidesPerView={2}>...</Carousel>

Autoplay and loop

Pauses on hover and focus; does not run with prefers-reduced-motion.

preview
Slide 1
autoplay={3000}
autoplay.tsx
<Carousel aria-label="..." loop autoplay={3000}>...</Carousel>

Controlled

preview
Slide: 1
Slide 1
index
controlled.tsx
const [index, setIndex] = useState(0);
<Carousel aria-label="..." index={index} onIndexChange={setIndex}>...</Carousel>

Colors

preview
Slide 1
primary
Slide 1
success
Slide 1
warning
Slide 1
danger
colors.tsx
<Carousel variantColor="primary" ...>
<Carousel variantColor="success" ...>
<Carousel variantColor="warning" ...>
<Carousel variantColor="danger" ...>

Custom color

preview
Slide 1
Pink
custom-color.tsx
<Carousel customColor="#db2777" ...>

Props

PropValuesDefaultDescription
childrenReactNode—One slide per child
aria-labelstring—Accessible name of the carousel
index / defaultIndexnumber0Controlled / initial first visible slide
onIndexChange(index: number) => voidnoneCalled when the position changes
slidesPerViewnumber1Slides visible at once
loopbooleanfalseWrap from the last position to the first
autoplayboolean | numberfalseAdvance every N ms (true = 5000). Pauses on hover/focus
showArrows / showDotsbooleantrueShow the arrows / dots
previousLabel / nextLabelstringPrevious slide / Next slideAccessible names of the arrows
dotLabel(index) => stringGo to slide NAccessible name of each dot
slideLabel(index, total) => stringN of totalAccessible name of each slide
variantColorprimary | success | warning | dangerprimaryAccent color (play button, progress, dots)
customColorstring | { light, dark }noneAny CSS color (or a pair per theme). Overrides variantColor
sizesm | md | lgmdSize of the controls and text
radiusnone | sm | md | lg | fulllgCorner rounding
animationnone | smooth | fast | bouncesmoothTransition of the controls

Accessibility

  • The root is a `<section>` with `aria-roledescription="carousel"` and the `aria-label` you pass.
  • Each slide is a `role="group"` with `aria-roledescription="slide"` and a name from `slideLabel` (default `1 of 5`).
  • Slides out of view are `aria-hidden` and `inert`, so their content is neither read nor focusable.
  • The arrows are buttons named by `previousLabel` / `nextLabel` (disabled at the ends unless `loop`), and the dots are buttons named by `dotLabel` with `aria-current="true"` on the current one.
  • Autoplay pauses while the pointer is over the carousel or focus is inside it, and does not run at all under `prefers-reduced-motion: reduce`; the slide transition is also removed there.
  • The slide area is `aria-live="off"` while autoplay runs and `polite` otherwise, so manual changes are announced.

Keyboard

KeyAction
ArrowLeft / ArrowRightPrevious / next slide (wraps with `loop`)
Home / EndFirst / last slide
TabMoves through the arrows, dots and focusable content of the visible slides

Keep in mind

  • Autoplay has no pause button; hover or focus pauses it. Prefer no autoplay, or a long delay, for content people need to read.
  • Alt text of images, and the labels (`aria-label`, `slideLabel`, `dotLabel`, arrows) in the page language, are up to your app.