You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Filed in May when the premise was that neither animation path worked reliably on native. That's no longer true — Vy UI animates today. This is now the next piece of work, not a hole in what's shipped: give the components that still have no motion a default, and collapse the two systems into one.
What animates today
Overlays — Dialog, AlertDialog, Sheet, DropdownMenu, via the shared vyui-fade-* / vyui-zoom-* / vyui-slide-* keyframes in packages/core/src/components/Presence/presence.css, driven by Presence-toggled ui-entering / ui-leaving classes. Runs on native and web.
Kit surfaces — Modal, Drawer, Tray, Toast, Progress carry their own animation/transition in the component + theme files.
Gesture settles — Draggable, SwipeAction, ToastSwipe and Swiper's snap loop animate through main-thread element.animate() (shared/composables/useAnimate.ts).
What doesn't
Accordion, Collapsible, Popover, Combobox, Tabs, Checkbox indicator, RadioGroup indicator — appear and disappear instantly. Each exposes reka-ui-style forceMount so a consumer can wrap it in their own transition, but there's no built-in motion.
List reorder / TransitionGroup FLIP — unsupported. No synchronous bounding-rect from the background thread.
The work
Default motion for the components above. Mostly a matter of extending the presence.css vocabulary — the classes and lifecycle already exist.
One system, not two. Overlays animate via CSS keyframe classes; gestures via useAnimate() / bespoke MT loops. Durations and easings are defined twice with nothing shared between them. Pick the canonical path (or a shared token layer over both) before adding more.
useAnimate() into the Presence mount/unmount lifecycle — portalled enter/leave is CSS-only today.
FLIP stays parked until there's a way to read layout synchronously.
Platform notes (learned on device, keep in mind when picking the path)
CSS keyframes are the resilient path. Class/keyframe-driven animation survives a background-thread style flush; main-thread inline-style animation gets wiped by any BG re-render. transition: height between two concrete px values also tweens on native (measure via @layoutchange, then px→px — MT setStyleProperty('height') is a no-op).
Lynx Web's animate() ignores WAAPI fill and easing (mapTimingOptions reads only fillMode/timingFunction/iterationCount). Every call site writes the end state inline first and passes both key spellings. lynx-family/lynx#2329 is the PR that made animate() available at all.
Never use rAF-tick counts as a timeout — lost animation events wedged Presence on web until a wall-clock watchdog replaced them (feat: web parity for gesture surfaces #161). requestAnimationFrame itself is normalised in shared/utils/delayFrames.ts.
Dropping upstream-blocked — nothing here waits on Lynx anymore.
Filed in May when the premise was that neither animation path worked reliably on native. That's no longer true — Vy UI animates today. This is now the next piece of work, not a hole in what's shipped: give the components that still have no motion a default, and collapse the two systems into one.
What animates today
vyui-fade-*/vyui-zoom-*/vyui-slide-*keyframes inpackages/core/src/components/Presence/presence.css, driven by Presence-toggledui-entering/ui-leavingclasses. Runs on native and web.element.animate()(shared/composables/useAnimate.ts).What doesn't
forceMountso a consumer can wrap it in their own transition, but there's no built-in motion.TransitionGroupFLIP — unsupported. No synchronous bounding-rect from the background thread.The work
presence.cssvocabulary — the classes and lifecycle already exist.useAnimate()/ bespoke MT loops. Durations and easings are defined twice with nothing shared between them. Pick the canonical path (or a shared token layer over both) before adding more.useAnimate()into the Presence mount/unmount lifecycle — portalled enter/leave is CSS-only today.Platform notes (learned on device, keep in mind when picking the path)
transition: heightbetween two concrete px values also tweens on native (measure via@layoutchange, then px→px — MTsetStyleProperty('height')is a no-op).animate()ignores WAAPIfillandeasing(mapTimingOptionsreads onlyfillMode/timingFunction/iterationCount). Every call site writes the end state inline first and passes both key spellings. lynx-family/lynx#2329 is the PR that madeanimate()available at all.requestAnimationFrameitself is normalised inshared/utils/delayFrames.ts.Dropping
upstream-blocked— nothing here waits on Lynx anymore.Related