DOCS / UI REFERENCE
Animation
Tweens run on the host timer (16ms ticks through the C++ scheduler) and set React state, so every animated style flows through the normal setProps → repaint path — no separate animation system to learn.
CSS-style transitions (since 0.0.26)
The declarative path: put transition classes on a node and its style changes tween from the currently displayed values instead of jumping — mid-flight re-renders retarget smoothly, exactly like the web.
<View
className={cx(
"h-2 rounded-full transition-colors duration-300 ease-out",
hot ? "bg-red-500" : "bg-zinc-700",
)}
/>transitionanimates opacity, colors, transforms, and blur;transition-all/colors/opacity/transform/nonescope it.duration-*anddelay-*are literal milliseconds;ease-linear/in/out/in-outpick the curve.- Since 0.0.27,
transitionEasingalso accepts any CSScubic-bezier(x1,y1,x2,y2)spec alongside the four named curves — set it via thestyleprop, e.g.style={{ transitionEasing: "cubic-bezier(0.34, 1.56, 0.64, 1)" }}. Parsed curves are cached by their string; malformed specs fall back to ease-in-out. - Keyframe presets:
animate-spin,animate-pulse, andanimate-bounceloop until the class comes off. - Honest limit: native
hover:/active:/focus:merges apply in C++ without a JS round-trip, so they can't transition — animate hover withonMouseEnterstate when you need it smooth.
useTween
import { useTween, lerp, Easing } from "@vsreact/core";
function Splash() {
const t = useTween({ duration: 600, delay: 150, easing: Easing.outExpo });
return (
<View
className="items-center justify-center"
style={{ opacity: t, marginTop: lerp(24, 0, t) }}
>
<Text className="text-2xl font-bold">STASHTRACK</Text>
</View>
);
}useTween({duration, delay?, easing?, onComplete?})— eased progress 0→1, starting on mount. Remount (viakey) to replay.Easing—linear,outCubic,inOutCubic,outExpo,outBack,outQuint, or any(t) => tfunction.lerp(from, to, t)— map progress onto any numeric style value.
useSpring
For interactive motion where a fixed-duration tween feels wrong — toggle thumbs, drawers, meters chasing levels — useSpring gives you a value that physically springs toward its target whenever the target changes:
import { useSpring } from "@vsreact/core";
function Drawer({ open }: { open: boolean }) {
const x = useSpring(open ? 0 : -240, { stiffness: 220, damping: 26 });
return <View className="absolute inset-y-0 w-[240]" style={{ left: x }} />;
}useSpring(target, {stiffness?, damping?, mass?, restDelta?})— defaults 170 / 24 / 1. Lower damping bounces; higher snaps.- Retargeting mid-flight keeps the current velocity — motion stays continuous when the user toggles quickly. The built-in
Toggleanimates its thumb this way. springStep(position, velocity, target, options, dtMs)— the pure integrator, exported for driving springs from your own loops.
Staggered sequences
Compose entrances by giving each element its own delay — the StashTrack splash staggers logo, wordmark, and status line this way:
const logo = useTween({ duration: 500, easing: Easing.outBack });
const word = useTween({ duration: 500, delay: 120, easing: Easing.outCubic });
const line = useTween({ duration: 400, delay: 260 });Timers
setTimeout and setInterval work inside the engine — they are backed by the same native scheduler, so a polling loop or a debounce behaves exactly like on the web. useTween is built on them.