SwipiDocumentation

API

useSwipiCarousel

Every option, its default and what it actually changes.

Signature

Every option is optional — useSwipiCarousel on its own is a working carousel, and it hands back a ref for the viewport and an object of state.

React
import { useSwipiCarousel } from '@midstem/swipi-react'
import type { SwipiCarouselOptions, SwipiCarousel } from '@midstem/swipi-react'

const [carouselRef, carousel] = useSwipiCarousel(options?: SwipiCarouselOptions)

Options

OptionTypeDefaultDescription
axis'x' | 'y''x'Direction the carousel moves in. With 'y' the slides are stacked and the swipe becomes vertical — see Vertical carousel for the CSS that goes with it.
loopbooleanfalseMakes the carousel infinite. The real slides are moved around, not cloned, so every slide stays a single DOM node.
dragFreebooleanfalseKeeps the momentum of a drag without snapping to a slide — the track coasts and rests wherever it stops. With false one gesture moves by one slide at most, however far it was dragged.
autoplaybooleanfalseAdvances the carousel on its own.
autoplaySpeednumber4000Interval between automatic moves, in milliseconds.
animationSpeednumber300Duration of the carousel's own movement, in milliseconds. A flick keeps its own duration, derived from how fast you were moving.
respectReducedMotionbooleanfalseWatches prefers-reduced-motion and jumps to the target instead of animating while it is set. Off by default — the carousel animates the same for everyone until you ask it not to.
startIndexnumber0Index of the snap position to open on, counted from zero like every other index in the API. Applied once, on mount, and clamped to the last snap.
slideWidthnumberWritten onto the track as the --swipi-slide-width custom property and nothing else. Sizes a slide only if your CSS reads it, along the axis the carousel moves in. Measuring still happens in the DOM.
spaceBetweennumberThe same for the gap, as --swipi-slide-gap.
onSelect(state: SwipiState) => void() => {}Called on every state change with the full navigable state.
onChange(positions: SlidePositions) => void() => {}Called when the current index changes, with the previous, current and next indexes, counted from zero.

All of them at once

React
const [carouselRef, carousel] = useSwipiCarousel({
  axis: 'x',
  loop: true,
  dragFree: false,
  autoplay: true,
  autoplaySpeed: 4000,
  animationSpeed: 300,
  respectReducedMotion: true,
  startIndex: 0,
  slideWidth: 300,
  spaceBetween: 12,
  onSelect: (state) => console.log(state.selectedIndex),
  onChange: ({ prev, current, next }) => console.log(prev, current, next)
})

Callbacks are read through a reference, so handing over a new function does not re-subscribe anything and does not fire an extra call. Options are read on every render, so a piece of state is all it takes. Flipping autoplay or loop is how you pause or unlock a carousel at runtime.

@ Copyright 2026 Midstem. All rights reserved.

DocsMidstemGitHubLinkedin