Skip to content

About

Instagram/TikTok-style vertical swipe pager for React. Mount any view per slot — Virtualized, SSR-safe, zero-dependency.

Topics

Resources

Stars

2 stars

Watchers

0 watching

Forks

Repository files navigation

short-form-view — Instagram/TikTok-style vertical swipe pager for React

Instagram / TikTok-style vertical swipe pager for React. A smooth, virtualized, SSR-safe vertical feed — render any view per slot.


React TypeScript dependencies coverage tests license


Features

  • Gesture-driven — configurable swipe threshold, velocity flick, edge resistance, and per-input controls. Touch, mouse, wheel, and keyboard all drive one engine.
  • Virtualized — only the active item ± overscan are mounted.
  • Data-change safe — appending never reflows existing items; opt in to key-based active item preservation for prepends/reorders.
  • Zero runtime dependency — no animation library, no CSS import.
  • SSR-safe — works in Next.js (App Router and Pages).
  • Rich callbacks — swipe, item enter/leave lifecycle, prefetch hints, and left/center/right press-hold + tap zones.
  • No re-render on drag — the track transform is written imperatively via requestAnimationFrame.

Install

pnpm add short-form-view   # react >= 18 is a peer dependency

Quick start

'use client'
import { useCallback, useState } from 'react'
import { ShortFormView } from 'short-form-view'

type Clip = { id: string; src: string }

export default function Feed() {
  const [clips, setClips] = useState<Clip[]>(initialClips)

  const loadMore = useCallback(() => {
    fetchMore().then((more) => setClips((prev) => [...prev, ...more]))
  }, [])

  return (
    <ShortFormView
      data={clips}
      keyExtractor={(c) => c.id}
      threshold={0.2}                                   // commit a swipe at 20% of the viewport
      onSwiped={({ from, to, direction }) => track(from, to, direction)}
      onIndexChange={(i, { reason }) => console.log('now at', i, 'via', reason)}
      onEndReached={loadMore}                           // append more, no reflow
      renderItem={(clip, state) => (
        <video
          src={clip.src}
          muted
          loop
          autoPlay={state.isActive}                     // play only while focused
          style={{ width: '100%', height: '100%', objectFit: 'cover' }}
        />
      )}
    />
  )
}

renderItem returns any React node, so a slot can be a video, an image, or any custom component — the library just connects them into the swipe feed.

What you get

Navigation drag · wheel/trackpad · keyboard (arrows, page, home/end) · controlled & uncontrolled index · imperative ref (scrollToIndex / next / prev) · optional key-preserved data changes
Tuning threshold (fraction or px) · velocityThreshold · resistance · loop · transitionDuration · easing · overscan · swipeEnabled / wheelEnabled / keyboardEnabled
Callbacks onSwiped · onIndexChange · onItemEnter / onItemLeave · onPrefetch · onEndReached · onHoldStart / onHoldEnd / onTapZone
Per-item state isActive · isVisible · isSnapping · distance · index / activeIndex

Full props, types, and the imperative handle: see the package README.

Press-and-hold vs. swipe

The active slot is overlaid with left / center / right zones. A stationary press past holdDelay fires onHoldStart (pause the video, dim the UI); a quick press-release fires onTapZone. Any vertical movement past a small slop becomes a swipe instead — so holding and swiping never fight.

Interactive descendants are protected by default: buttons, links, form controls, editable content, and elements marked with data-sfv-ignore-gesture do not start feed gestures.

Repository

Path What
packages/short-form-view the library — gesture engine, virtualization, item lifecycle, SSR utils
examples/next-demo Next.js App Router demo with live controls and infinite append
docs/superpowers design spec + implementation plan
pnpm install
pnpm -C examples/next-demo dev          # http://localhost:3100
pnpm test                                # unit (vitest)
pnpm -C packages/short-form-view test:cov
pnpm -C examples/next-demo test:e2e      # Playwright E2E + visual

License

MIT

About

Instagram/TikTok-style vertical swipe pager for React. Mount any view per slot — Virtualized, SSR-safe, zero-dependency.

Topics

Resources

Stars

2 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages