SnapCarousel is a controlled carousel with discrete slides, navigation arrows, and dot indicators. It supports keyboard navigation, touch/swipe gestures, and provides an imperative API for programmatic control.
A simple carousel with arrow navigation and dot indicators:
<SnapCarousel> <div>Slide 1</div> <div>Slide 2</div> <div>Slide 3</div> <div>Slide 4</div> </SnapCarousel>
Control the current slide index externally with index and onIndexChange:
Current index: 0
const [index, setIndex] = createSignal(0);
<SnapCarousel index={index()} onIndexChange={setIndex}>
<div>Controlled Slide 1</div>
<div>Controlled Slide 2</div>
<div>Controlled Slide 3</div>
</SnapCarousel>
<Button onClick={() => setIndex(0)} label="Go to first" />
<Button onClick={() => setIndex(2)} label="Go to last" />Hide the dot indicators with showDots={false}:
<SnapCarousel showDots={false}>
<div>Slide A</div>
<div>Slide B</div>
<div>Slide C</div>
</SnapCarousel>Use a ref to access methods for programmatic navigation:
let carouselRef: SnapCarouselRef | undefined;
<SnapCarousel ref={(ref) => (carouselRef = ref)}>
<div>Item 1</div>
<div>Item 2</div>
<div>Item 3</div>
</SnapCarousel>
<Button onClick={() => carouselRef?.prev()} label="Previous" />
<Button onClick={() => carouselRef?.next()} label="Next" />
<Button onClick={() => carouselRef?.goToSlide(2)} label="Go to slide 3" />| Name | Type | Default | Description |
|---|---|---|---|
children | JSXElement | required | Slide items to display |
index | number | 0 | Current active slide index (controlled mode) |
onIndexChange | (index: number) => void | undefined | Callback when slide changes |
showMultiple | boolean | false | Whether to show multiple items at once (visibility controlled by item styles) |
showDots | boolean | true | Whether to show dot indicators below the carousel |
prevIcon | string | "chevron-left" | Icon name for the previous button |
nextIcon | string | "chevron-right" | Icon name for the next button |
styles | StyleXStyles | undefined | Additional StyleX styles for the container |
arrowStyles | StyleXStyles | undefined | Additional StyleX styles for arrow buttons |
dotStyles | StyleXStyles | undefined | Additional StyleX styles for dot indicators |
ref | SnapCarouselRef | ((ref: SnapCarouselRef) => void) | undefined | Ref to access imperative API methods |
Access these methods via ref to control the carousel programmatically:
| Method | Type | Description |
|---|---|---|
goToSlide | (index: number) => void | Navigate to a specific slide by index |
next | () => void | Navigate to the next slide |
prev | () => void | Navigate to the previous slide |
Navigation via left/right arrow buttons (using Reef Button components)
Arrows are disabled at the ends (no wrap-around behavior)
Arrows are disabled when there are 0 or 1 children
Dot indicators below carousel allow direct navigation
Keyboard navigation with left/right arrow keys when focused
Touch/swipe gesture support on touch devices
Smooth CSS transitions when navigating (respects prefers-reduced-motion)
Scrolls by 1 item at a time
The SnapCarousel uses these theme variables for customization:
carouselGap - Gap between slides and UI elements
carouselDotSize - Size of dot indicators
carouselDotActiveColor - Color of the active dot
carouselDotInactiveColor - Color of inactive dots
carouselSnapAnimationTiming - Transition timing for slide changes
Uses role="region" with aria-roledescription="carousel"
Each slide has aria-roledescription="slide"
aria-live="polite" announces slide changes to screen readers
Dots use role="tablist" and role="tab" semantics
Keyboard navigable with arrow keys
Focus-visible outline on interactive elements
Respects prefers-reduced-motion preference
| Scenario | Behavior |
|---|---|
| 0 children | Renders nothing |
| 1 child | Shows item, arrows disabled, no dots |
| index out of bounds | Clamped to valid range (0 to children.length - 1) |