react-swipeable
A lightweight React hook for detecting and handling swipe gestures on touch and mouse events.
Repository Health
Technical Analysis
react-swipeable exports a single hook, useSwipeable, that turns native touch and mouse drag interactions into a normalized swipe-event model. Spreading the returned handlers onto any DOM element gives you directional callbacks (onSwipedLeft/Right/Up/Down), a generic onSwiped/onSwiping/onSwipeStart lifecycle, and tap detection, along with delta, velocity, and displacement data for each swipe.
The library has zero runtime dependencies beyond a React peer dependency, tracks gesture state in refs rather than React state to avoid re-render thrash on high-frequency touchmove events, and ships configuration for per-direction delta thresholds, swipe duration cutoffs, rotation angle, mouse tracking, and passive-listener behavior for scroll prevention.
What You Get
- A single useSwipeable() hook returning spreadable ref/onMouseDown handlers
- Directional callbacks (onSwipedLeft, onSwipedRight, onSwipedUp, onSwipedDown) plus onSwipeStart, onSwiping, onSwiped, and onTap lifecycle events
- Full TypeScript types for SwipeEventData, SwipeableProps, and handler signatures
- Configurable delta thresholds (overall or per-direction), swipe duration cutoff, rotation angle, and touch passive-listener options
- Optional mouse-drag tracking (trackMouse) so swipe gestures work with a mouse in addition to touchscreens
Common Use Cases
- Swipeable image carousels and product galleries
- Swipe-to-dismiss cards, notifications, and list items
- Mobile-style navigation drawers opened and closed via swipe
- Testing swipe interactions with mouse input during desktop development
Under The Hood
Architecture The library tracks gesture state in useRef-backed objects (transientState, transientProps) rather than React state, so touchmove updates never trigger re-renders; a getHandlers factory closes over a set function that applies reducer-style updates to that ref state, while an onRef callback attaches native touchstart/touchmove/touchend (and, when trackMouse is set, mousedown/mousemove/mouseup) listeners directly to the DOM element via addEventListener/removeEventListener, decoupling gesture tracking entirely from React’s synthetic event and render cycle. An updateTransientState function reconciles listener attachment/detachment whenever trackTouch or preventScrollOnSwipe change between renders. The whole implementation lives in one file, src/index.ts, with types isolated in src/types.ts — a deliberately flat, single-hook architecture with no internal layering.
Tech Stack Written in TypeScript with no runtime dependencies; react is declared only as a peerDependency (^16.8.3 through ^19). Builds run through tsc (for .d.ts output) and Rollup, producing CJS (lib/), ESM (es/), and UMD (dist/) bundles, each gated by a size-limit budget of under 2KB gzipped. The package’s own documentation site is a separate Docusaurus + Tailwind CSS application under docs/, deployed independently of the library.
Code Quality A single, extensive test file (tests/useSwipeable.spec.tsx, over a thousand lines) built on @testing-library/react and Jest/ts-jest exercises all four swipe directions, delta configuration, swipeDuration, trackMouse, preventScrollOnSwipe, and ref re-attachment behavior, backed by committed snapshots. ESLint extends eslint:recommended, the TypeScript-ESLint recommended set, and plugin:react/recommended, with react-hooks/rules-of-hooks enforced as an error and exhaustive-deps as a warning; Prettier formatting is checked in CI alongside linting and the unit test suite via a GitHub Actions workflow. No untyped escape hatches beyond an explicitly permitted any usage.
API Design The hook’s central design choice is to keep all gesture-tracking state out of React’s render cycle entirely — consumers get updates purely through the callback props they pass in, not a returned state object, trading a fully reactive “is swiping” value for a leaner hook that avoids allocation and re-render overhead during rapid touchmove events. The public surface is intentionally minimal: one hook, one spread of handlers, config options that mirror the callback names. Compared to broader gesture libraries like @use-gesture/react (drag, pinch, wheel, scroll), react-swipeable deliberately does one thing — swipe direction detection — with zero dependencies and a very small bundle, prioritizing ergonomics and footprint over feature breadth.
Used by 2 apps in this directory
Actual
Invoicing Finance
Local-first personal finance with envelope budgeting, end-to-end encryption, and multi-device sync — no subscription required.
Blinko
Knowledge Management · Note Taking
A self-hosted, AI-powered card note-taking tool that lets you capture fleeting thoughts instantly and retrieve them with natural language search.