Skip to content
60fps/ui

60fps/ui

A collection of headless interaction engines — carousel, drag, motion and scroll-reveal — written once in framework-agnostic TypeScript, then wrapped in thin, idiomatic adapters for React and Vue.

The engine owns the behaviour (DOM measurement, event listeners, data-* attributes, an event emitter); the adapter owns the lifecycle and reactivity for your framework. Swap the adapter, keep the engine.

The two layers

Every primitive is split the same way:

Layer What it does Example
Engine Vanilla class extending an Emitter, with init(el) / clean(). No framework imports. new CarouselEngine()
Adapter A hook/composable that instantiates the engine, drives init/clean, and mirrors state. useCarousel(ref)

This means the hard part — the interaction logic — has a single implementation and a single test suite, while each framework gets an API that feels native to it.

Packages

Package Contents
@60fps/ui-utils Shared primitives: Emitter, DOM helpers, math, ResizeObserver / IntersectionObserver managers
@60fps/ui-motion Motion — animate a value with spring, damping or inertia
@60fps/ui-drag DragEngine — pointer & touch drag gestures
@60fps/ui-carousel CarouselEngine — accessible scroll-snap carousel
@60fps/ui-inview InViewEngine + portable CSS — reveal on viewport entry
@60fps/ui-video VideoEngine + PosterVideoEngine — polite playback & lazy poster→video
@60fps/ui-react React hooks for every engine (@60fps/ui-react/carousel-engine, …)
@60fps/ui-vue Vue composables for every engine (@60fps/ui-vue/carousel-engine, …)

Install

# React
pnpm add @60fps/ui-react @60fps/ui-motion @60fps/ui-drag @60fps/ui-carousel @60fps/ui-inview @60fps/ui-video

# Vue
pnpm add @60fps/ui-vue @60fps/ui-motion @60fps/ui-drag @60fps/ui-carousel @60fps/ui-inview @60fps/ui-video

Head to Motion to see the pattern in action, or jump straight to Carousel and InView.