Headless Core — Carousel
Powers Carousel internally. No autoplay timer, no swipe/drag handling, and no transform/scroll math — those are real DOM/timing concerns the consuming component owns. This factory only tracks which index is active and hands back the ARIA wiring.
import { createCarousel } from '@andersseen/headless-components/carousel';
const carousel = createCarousel({ slideCount: 5, defaultIndex: 0, onIndexChange: index => console.log('Active slide:', index),});
carousel.actions.goToNext();carousel.queries.isActive(1); // true after the call aboveConfig
Section titled “Config”| Option | Type | Default | Notes |
|---|---|---|---|
slideCount | number | 0 | |
defaultIndex | number | 0 | Normalized modulo slideCount on creation. |
autoplay | boolean | false | Just a state flag — starting/stopping a timer from it is up to you. |
interval | number (ms) | — | Accepted by the config type; not read internally — same reasoning as autoplay. |
onIndexChange | (index: number) => void | — |
activeIndex, slideCount, autoplay.
Actions & queries
Section titled “Actions & queries”| Member | Signature | Notes |
|---|---|---|
actions.goToNext() / goToPrev() | () => void | Wraps around at either end. |
actions.goToSlide(index) | (index: number) => void | Also wraps — negative or out-of-range indexes are normalized modulo slideCount. |
actions.setSlideCount(count) | (count: number) => void | Resets activeIndex to 0 if it’s now out of range. |
actions.setAutoplay(v) | (autoplay: boolean) => void | |
queries.isActive(index) | (index: number) => boolean |
Prop-getters
Section titled “Prop-getters”| Getter | Returns |
|---|---|
getTrackProps(trackId) | aria-live ('off' while autoplay, else 'polite'), aria-label: 'Slides' |
getSlideProps(index, label?) | role: 'group', aria-roledescription: 'slide', aria-label (defaults to Slide N), aria-hidden (true for every non-active slide) |
getPrevButtonProps(trackId) / getNextButtonProps(trackId) | aria-controls: trackId, aria-label |
aria-live switching off during autoplay is deliberate — a screen reader
shouldn’t announce every auto-advance, only manual navigation.
Live example
Section titled “Live example”Next steps
Section titled “Next steps”Primitives — every factory above follows the same
state/subscribe/actions/queries/prop-getter shape this one does.