Carousel
Scroll-snap carousel with mouse drag, loop, autoplay that pauses itself, and dots that fill with the timer.
Built on Icons.
Installation
npx shadcn@latest add https://neonkit.heyaadi.com/r/carousel.jsonUsage
import { Carousel, CarouselContent, CarouselDots, CarouselItem, CarouselNext, CarouselPrevious } from "@/components/ui/carousel"
<Carousel aria-label="Releases" className="sm:[--slides:2] lg:[--slides:3]">
<CarouselContent>
<CarouselItem>…</CarouselItem>
</CarouselContent>
<CarouselDots />
<CarouselPrevious />
<CarouselNext />
</Carousel>Examples
Autoplay
The active dot is a tube that fills with the timer. It pauses on hover, focus and hidden tabs, keeps its place, and never runs under reduced motion.
Gallery with progress
Fractional --slides shows the next card peeking in. The lit segment tracks the scroll, drags included.
Vertical
orientation="vertical" scrolls on the y axis; give the viewport a height.
API reference
Carousel
Renders a section with aria-roledescription="carousel". Give it an aria-label. Accepts every native section attribute.
| Prop | Type | Default |
|---|---|---|
orientation | "horizontal"Scroll axis. Arrow keys follow it. | "horizontal" |
loop | booleanPrevious and next wrap around at the ends. | false |
autoplay | booleanAdvances on a timer; a number is the delay in ms (5000 by default). Always wraps. | false |
defaultIndex | numberStarting position, jumped to without animation. | 0 |
onSlideChange | (index: number) => voidCalled when the snap position changes, by any means. | None |
apiRef | Ref<CarouselApi>scrollTo(i), next(), prev(), getIndex(), getCount(), play() and pause(). | None |
color | NeonColorPalette name or hex. Falls back to --neon-accent, then cyan. | inherited |
CSS variables
Set on Carousel, with responsive variants, e.g. className="[--slides:1] md:[--slides:3]".
| Prop | Type | Default |
|---|---|---|
--slides | numberSlides in view. Fractions let the next one peek in. | 1 |
--gap | lengthSpace between slides. | 16px |
CarouselContent
The scroll-snap viewport and its track. Accepts every native div attribute for the track.
| Prop | Type | Default |
|---|---|---|
viewportClassName | stringClasses for the scrolling viewport. Vertical carousels need a height here. | None |
CarouselItem
One slide: role="group", aria-roledescription="slide", labelled "2 of 6" unless you pass aria-label.
| Prop | Type | Default |
|---|
CarouselPrevious, CarouselNext
Icon buttons, disabled at the ends unless loop is on. Pass children to replace the chevron.
| Prop | Type | Default |
|---|
CarouselDots, CarouselProgress, CarouselPlayToggle
Dots are one button per snap position. Progress is a decorative track with a lit segment. The play toggle only renders when autoplay is on.
| Prop | Type | Default |
|---|
Accessibility
- Built on native scroll snap: touch, trackpads and the mouse wheel all scroll it, and nothing is measured per frame.
- The viewport is a polite live region, so assistive tech hears the new slide after next or previous. It goes quiet while autoplay runs.
- Autoplay stops for hover, keyboard focus and hidden tabs, and the pause button stops it for good. WCAG 2.2.2 needs that button, so render it.
- Arrow keys move between slides when focus is on a dot, a button or the viewport.
- A drag never fires the click it ended on, so slides can hold links.
- Under prefers-reduced-motion, scrolling jumps instead of gliding and autoplay is off.