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:

LayerWhat it doesExample
EngineVanilla class extending an Emitter, with init(el) / clean(). No framework imports.new CarouselEngine()
AdapterA 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

PackageContents
@60fps/utilsShared primitives: Emitter, DOM helpers, math, ResizeObserver / IntersectionObserver managers
@60fps/motionMotion — animate a value with spring, damping or inertia
@60fps/dragDragEngine — pointer & touch drag gestures
@60fps/carouselCarouselEngine — accessible scroll-snap carousel
@60fps/inviewInViewEngine + portable CSS — reveal on viewport entry
@60fps/videoVideoEngine + PosterVideoEngine — polite playback & lazy poster→video
@60fps/reactReact hooks for every engine (@60fps/react/carousel-engine, …)
@60fps/vueVue composables for every engine (@60fps/vue/carousel-engine, …)

Install

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

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

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