lynx-ui logo
lynx-ui

@lynx-js/motion

@lynx-js/motion is a thin adaptation layer that reuses Motion's source directly to bring its imperative JavaScript APIs to Lynx. All APIs run in the main-thread script environment, so animations update visual properties immediately without round-tripping through the background thread. If you know Motion's animate(), motionValue(), and spring on the web, you already know how to use them in Lynx. If you are new to Motion, the Motion quick-start guide covers the fundamentals.

What is Mini and when should I use it?

The package ships two entries. The full entry has not yet reached full feature parity with Motion and has higher engine requirements. Mini is a trimmed-down build with broader compatibility, and is the entry used by lynx-ui today.

@lynx-js/motion@lynx-js/motion/mini (Mini)
Animationnumbers, colors, unit strings, keyframe arraysnumbers only
Motion valuesmotionValue() (useMotionValue not yet supported)useMotionValueRef()
Springtype: 'spring'type: 'spring'
Staggerstagger() with selectors--
styleEffectderive styles from motion values--
Lynx Engine>= 3.5no minimum
ReactLynx>= 0.115.2no minimum
Bundle size~275 KB~135 KB

Install

npm
yarn
pnpm
bun
deno
npm install @lynx-js/motion

Import from the main package entry:

import { animate, motionValue, styleEffect } from '@lynx-js/motion';

Animate an element ref

The animate() function accepts the same options as Motion on the web, including duration, ease, delay, repeat, and type: 'spring'. See the Motion animate() reference for the full option list.

The usual pattern is:

  1. Create a main-thread element ref with useMainThreadRef().
  2. Attach it to the element with main-thread:ref.
  3. Start animate() inside a main-thread function.
  4. Store the animation controls in another main-thread ref so cleanup can call stop().

Use Springs

Set type: 'spring' when a value should settle with spring physics instead of following a fixed-duration easing curve. All spring options from Motion are supported, including stiffness, damping, mass, and bounce.

Use Motion Values

motionValue() stores a value, can be animated directly with animate(), and lets you subscribe to changes. Use it when multiple effects or event handlers need a shared animated value.

Build Gesture Effects

For high-frequency touch input, keep the event handlers on the main thread with main-thread:bindtouchstart, main-thread:bindtouchmove, and main-thread:bindtouchend. Use motion values with styleEffect() to derive visual state from gesture state.

Info

Motion's web-only gesture APIs such as scroll(), inView(), hover(), and press() are not part of @lynx-js/motion. Use the main-thread touch events shown above instead.

Except as otherwise noted, this work is licensed under a Creative Commons Attribution 4.0 International License, and code samples are licensed under the Apache License 2.0.