# swipi

> Headless TypeScript carousel hook for React

Latest version **3.1.0** (published 2026-08-13) · MIT license · 0 weekly downloads

## Install

```sh
npm install swipi
pnpm add swipi
yarn add swipi
bun add swipi
```

## Health

**Score 70/100 (B)** — status: active.

Positive: has types; esm support; no vulnerabilities; recently updated; high maintenance score; high quality score.

Warnings: low downloads.

## Facts

| | |
|---|---|
| Version | 3.1.0 |
| Published | 2026-08-13 |
| First published | 2023-04-05 |
| Weekly downloads | 0 |
| License | MIT |
| TypeScript types | bundled |
| Module format | ESM + CommonJS |
| Dependencies | 0 |
| Unpacked size | 34.9 KB |
| Known vulnerabilities | 0 |
| Install scripts | no |
| GitHub stars | 10 |
| Author | Maksym Tkachuk, Oleksandr Didyshen |
| Maintainers | dom_dev |
| Keywords | react, typescript, headless, carousel, react-hook, infinite-carousel, image-carousel |

## Links

- npm: https://www.npmjs.com/package/swipi
- Repository: https://github.com/midstem/swipi
- Homepage: https://swipi.midstem.net/
- Issues: https://github.com/midstem/swipi/issues
- npm.io page: https://npm.io/package/swipi

## Alternatives

- [mobx-react](https://npm.io/package/mobx-react.md) — 2.8M weekly downloads
- [rc-tree](https://npm.io/package/rc-tree.md) — 2.6M weekly downloads
- [@react-oauth/google](https://npm.io/package/@react-oauth/google.md) — 1.3M weekly downloads
- [@wagmi/connectors](https://npm.io/package/@wagmi/connectors.md) — 877.0K weekly downloads
- [vee-validate](https://npm.io/package/vee-validate.md) — 836.4K weekly downloads

## Recent versions

- 3.1.0 (latest) — 2026-08-13
- 3.0.2 — 2026-08-11
- 3.0.1 — 2026-08-05
- 3.0.0 — 2026-08-04
- 2.0.1 — 2026-07-24
- 2.0.0 — 2026-07-24
- 1.1.8 — 2023-06-09
- 1.1.7 — 2023-05-26
- 1.1.6 — 2023-05-26
- 1.1.5 — 2023-05-24
- 1.1.4 — 2023-05-09
- 1.1.3 — 2023-04-24
- 1.1.2 — 2023-04-19
- 1.1.1 — 2023-04-12
- 1.1.0 — 2023-04-10
- … 2 more at https://npm.io/package/swipi/versions

## README

# Swipi

[![NPM version][npm-image]][npm-url] [![bundle size][bundlephobia-image]][bundlephobia-url]

[npm-image]: https://img.shields.io/npm/v/swipi.svg
[npm-url]: http://npmjs.org/package/swipi
[bundlephobia-image]: https://img.shields.io/bundlephobia/minzip/swipi?color=%238ab4f8&label=gzip%20size
[bundlephobia-url]: https://bundlephobia.com/result?p=swipi

<a href='https://midstem.net'>
  <img src='assets/midstem.png' height='60'>
</a>

<p><b>Swipi</b> is a headless carousel for React. One hook gives you the engine
— drag, momentum, snapping, looping, autoplay — and hands back a ref and a
small object of state. The markup, the CSS and the accessibility stay yours, so
nothing of ours ends up in your DOM and there is no stylesheet to import.</p>

<p>It weighs <b>5.1 KB gzipped</b> — 1.85× less than
<code>embla-carousel-react</code> with its autoplay plugin, measured through the
same build in
<a href="https://github.com/midstem/swipi/blob/main/SIZE.md">SIZE.md</a>.</p>

> Upgrading from Swipi 2? The `<Swipi>` component and its ~30 props are gone in
> 3.0 —
> [MIGRATION.md](https://github.com/midstem/swipi/blob/main/MIGRATION.md) maps
> every one of them to a hook option or a line of CSS.

### Installation

**npm**

```bash
$ npm install swipi
```

**yarn**

```bash
$ yarn add swipi
```

## 🔥 <a href='https://swipi.midstem.net'>View more examples and create a custom slider</a>

## **Basic Usage**

Wiring is a single ref on the viewport. The track is its only child and the
slides are the children of the track.

### The markup

```tsx
import { useSwipiCarousel } from 'swipi'

export const Carousel = ({ items }) => {
  const [carouselRef, carousel] = useSwipiCarousel({ loop: true })

  return (
    <>
      <div className="overflow-hidden touch-pan-y" ref={carouselRef}>
        <div className="flex -ml-3 select-none">
          {items.map((item) => (
            <div
              className="min-w-0 shrink-0 grow-0 basis-1/2 pl-3"
              key={item.id}
            >
              {item.title}
            </div>
          ))}
        </div>
      </div>

      <button
        type="button"
        onClick={carousel.scrollPrev}
        disabled={!carousel.canScrollPrev}
      >
        ‹
      </button>
      <button
        type="button"
        onClick={carousel.scrollNext}
        disabled={!carousel.canScrollNext}
      >
        ›
      </button>
    </>
  )
}
```

### The classes

Those three class lists are a contract, not decoration — the geometry depends on
them. Two of them are yours to tune: `basis-1/2` sets how many slides are
visible, and the `pl-3` on the slide with the matching `-ml-3` on the track sets
the space between them. Everything else on the page is styling you own.

Not using Tailwind? Our documentation provides examples using both Tailwind and plain CSS.

## **Documentation**

For advanced usage, available options, responsive layout specifics, state management, and accessibility guidelines, please refer to our full documentation at [https://swipi.midstem.net/docs/](https://swipi.midstem.net/docs/).

---
_Source: https://npm.io/package/swipi · Machine-readable twin of the npm.io package page. Health data is recomputed on every publish._
