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 MotionCascadeTier
animate={{ opacity: 1, x: 0 }}el.Animate().Fade(1f, .3f).MoveX(0f, .3f)Lite
initial={{ opacity: 0, y: 24 }}.From(0f) after each verbLite
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.SnappyPro
transition={{ type: "spring", visualDuration, bounce }}.WithResponse(response, bounce)Pro
Interruptions keep velocityBuilt in: a replaced spring hands its velocity to the new onePro
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
whileFocusel.OnFocus()Pro
staggerChildren: .05items.AnimateEach()….Stagger(.05f)Pro
<AnimatePresence> enter/exitel.Show(Transition…) / el.Hide(Transition…)Pro
Page transitionscontainer.SwapTo(screen, Transition.Crossfade(.3f))Pro
useReducedMotion()MotionSettings.Mode = MotionMode.ReducedLite
onAnimationComplete.OnComplete(…), or .OnSettled(…) to also hear about cancelsLite
useAnimate controlsthe 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, Top and Left verbs animate layout values directly.