SwipiDocumentation

Guides

Arrows

Previous and next buttons driven by canScrollPrev, canScrollNext and hasOverflow.

Two buttons and two methods

Arrows are real buttons calling scrollPrev and scrollNext on the carousel. Both methods are stable, so they can be bound straight to the click without a wrapper.

React
<button
  type="button"
  aria-label="Previous slide"
  onClick={carousel.scrollPrev}
  disabled={!carousel.canScrollPrev}
>
  ‹
</button>
<button
  type="button"
  aria-label="Next slide"
  onClick={carousel.scrollNext}
  disabled={!carousel.canScrollNext}
>
  ›
</button>
  • canScrollPrev and canScrollNext tell you whether the move is possible — use them for disabled rather than comparing indexes yourself.
  • Give each button an aria-label. A glyph or an icon leaves a screen reader with nothing to announce.
  • type="button" keeps the arrows from submitting a form they happen to sit inside.

Hiding the arrows entirely

A disabled pair of arrows on a list that already fits is noise. hasOverflow is false when there is nothing to scroll — when three slides sit in a viewport that shows three — so the controls can disappear along with the interaction.

React
const [carouselRef, carousel] = useSwipiCarousel()

return (
  <div className="carousel">
    <div className="carousel__viewport" ref={carouselRef}>
      {/* … */}
    </div>

    {carousel.hasOverflow && <Arrows carousel={carousel} />}
  </div>
)

With loop

An infinite carousel can always move in both directions, so as long as there is something to scroll both flags stay true and the buttons never disable. If you want the arrows to react to the position anyway, render them from selectedIndex and snapCount instead.

React
const [carouselRef, carousel] = useSwipiCarousel({ loop: true })

carousel.canScrollPrev // true, on every snap
carousel.canScrollNext // true, on every snap

@ Copyright 2026 Midstem. All rights reserved.

DocsMidstemGitHubLinkedin