Animations
Add a transition prop to any <View> and Glyx interpolates the change
instead of snapping to the new value:
<View
style={{ opacity: visible ? 1 : 0 }}
transition={{ duration: 200 }}
/>v1 scope: opacity only. This is the CSS-transition layer, not
Framer Motion parity. Transform/scale/color transitions and a full
spring/gesture animation API (useAnimatedValue, drag-to-dismiss,
staggered lists) are a separate, larger initiative — see the
v2 roadmap — and haven't been started.
Why this exists
Before this, animating anything meant hand-rolling it — a setInterval
loop pushing new style values from JS each frame, the same pattern used for
the auto-rotate demo in model-viewer. That's real per-frame JS work
crossing the FFI boundary 60+ times a second, and on QuickJS (no JIT) that
cost is higher than on V8. transition avoids it entirely.
How it works
JS declares the transition's intent once — on the render where the style
value changes, transitionMs is sent to Rust as a plain node prop.
Rust's render loop owns the interpolation from there: it samples an
eased value fresh every frame with zero JS re-entry, using an
ease-out cubic curve (the same "settle in" feel as most CSS-transition
defaults), and only re-renders while a transition is actually in flight —
static frames cost nothing extra. This is the same "JS drives state, Rust
is a dumb renderer" model used for 2D and GLTF animation playback elsewhere
in Glyx, just applied one level lower for this specific case.
API
| Prop | Type | Description |
|---|---|---|
transition.duration | number | Transition length in milliseconds. |
function Panel({ open }: { open: boolean }) {
return (
<View
style={{ opacity: open ? 1 : 0, backgroundColor: '#1A1A26' }}
transition={{ duration: 250 }}
>
<Text>Panel content</Text>
</View>
)
}Only opacity changes are interpolated today — other style properties on
the same node update immediately, as before.