Coming from Framer Motion
UI Toolkit borrowed CSS from the web, and Cascade borrows its animation model from Framer Motion. If you know one, here is the other.
| Framer Motion | Cascade | Tier |
|---|---|---|
animate={{ opacity: 1, x: 0 }} | el.Animate().Fade(1f, .3f).MoveX(0f, .3f) | Lite |
initial={{ opacity: 0, y: 24 }} | .From(0f) after each verb | Lite |
transition={{ duration: .3, ease: "easeOut" }} | duration on each verb, .Ease(Ease.OutCubic) | Lite |
transition={{ type: "spring", stiffness, damping }} | .Spring(new SpringConfig(stiffness, damping)) or SpringPreset.Snappy | Pro |
transition={{ type: "spring", visualDuration, bounce }} | .WithResponse(response, bounce) | Pro |
| Interruptions keep velocity | Built in: a replaced spring hands its velocity to the new one | Pro |
variants + animate="open" | el.Variants().State("open", s => …), then el.To("open") | Pro |
whileHover={{ scale: 1.05 }} | el.OnHover().ScaleTo(1.05f, .15f) | Pro |
whileTap={{ scale: .96 }} | el.OnPress().ScaleTo(.96f, .08f) | Pro |
whileFocus | el.OnFocus() | Pro |
staggerChildren: .05 | items.AnimateEach()….Stagger(.05f) | Pro |
<AnimatePresence> enter/exit | el.Show(Transition…) / el.Hide(Transition…) | Pro |
| Page transitions | container.SwapTo(screen, Transition.Crossfade(.3f)) | Pro |
useReducedMotion() | MotionSettings.Mode = MotionMode.Reduced | Lite |
onAnimationComplete | .OnComplete(…), or .OnSettled(…) to also hear about cancels | Lite |
useAnimate controls | the chain is the handle: h.Pause(), h.Resume(), h.Cancel() | Lite |
await animate(…) | await el.Animate()… (returns whether it finished) | Lite |
A button, ported
// Framer Motion
<motion.button
initial={{ opacity: 0, y: 24 }}
animate={{ opacity: 1, y: 0 }}
whileHover={{ scale: 1.05 }}
whileTap={{ scale: 0.96 }}
transition={{ type: "spring", stiffness: 210, damping: 22 }} />
// Cascade
button.OnHover().ScaleTo(1.05f, 0.15f, Ease.OutBack);
button.OnPress().ScaleTo(0.96f, 0.08f);
button.Animate()
.Fade(1f, 0f).From(0f).Spring(SpringPreset.Snappy)
.MoveY(0f, 0f).From(24f).Spring(SpringPreset.Snappy);
Differences worth knowing
- Durations are seconds, like Framer Motion, not milliseconds like Unity's own scheduler.
- Verbs in one chain run together.
.Then()starts the next step, where Framer Motion would use keyframes or a sequence. - Animations stop when the element leaves the panel, the way Framer Motion stops on unmount.
- There is no layout animation (FLIP). The
Width,Height,TopandLeftverbs animate layout values directly.