Terminal
1npm install next-transition-router framer-motion
Framer Motion with next-transition-router gives you full control over animation lifecycle (leave/enter). Ideal when you're already using Framer Motion in your project and want a consistent API for all animations.
npm install next-transition-router framer-motionTransitionRouter and leave/enter callbacksframer-motion/dom for direct DOM animationnext() when animation completes1npm install next-transition-router framer-motion
1'use client'23import { useRef } from 'react'4import { TransitionRouter } from 'next-transition-router'5import { animate, stagger } from 'framer-motion/dom'67export default function FramerMotionProvider({8 children,9}: {10 children: React.ReactNode11}) {12 const wrapperRef = useRef<HTMLDivElement>(null!)1314 return (15 <TransitionRouter16 auto17 leave={(next) => {18 const wrapper = wrapperRef.current19 const elements = wrapper.querySelectorAll('h1, p, .btn, .demo-badge, nav')2021 animate(22 elements,23 { opacity: [1, 0], y: [0, -20], filter: ['blur(0px)', 'blur(2px)'] },24 { duration: 0.3, delay: stagger(0.05), ease: [0.55, 0, 1, 0.45] }25 )2627 animate(28 wrapper,29 { opacity: [1, 0], scale: [1, 0.97] },30 { duration: 0.4, ease: [0.55, 0, 1, 0.45], delay: 0.1 }31 ).then(next)32 }}33 enter={(next) => {34 const wrapper = wrapperRef.current35 const elements = wrapper.querySelectorAll('h1, p, .btn, .demo-badge, nav')3637 animate(38 elements,39 { opacity: [0, 1], y: [30, 0], filter: ['blur(2px)', 'blur(0px)'] },40 { duration: 0.45, delay: stagger(0.06), ease: [0, 0, 0.2, 1] }41 )4243 animate(44 wrapper,45 { opacity: [0, 1], scale: [0.97, 1] },46 { duration: 0.4, ease: [0, 0, 0.2, 1] }47 ).then(next)48 }}49 >50 <div ref={wrapperRef}>{children}</div>51 </TransitionRouter>52 )53}
1import FramerMotionProvider from './providers'23export default function Layout({ children }: { children: React.ReactNode }) {4 return <FramerMotionProvider>{children}</FramerMotionProvider>5}