# Full examples and variants
## Working folder layout
```
app/
layout.tsx # persistent shell (html/body, providers)
template.tsx # remounts per route -> hosts AnimatePresence
page-transition.tsx # motion wrapper (enter/exit variants)
frozen-router.tsx # FrozenRouter (LayoutRouterContext snapshot)
page.tsx # home
about/page.tsx
globals.css
```
## Directional slide transitions
Track direction by comparing route depth or a route order map, then feed it to variants.
```tsx
// app/page-transition.tsx
'use client';
import { motion } from 'framer-motion';
import { usePathname } from 'next/navigation';
import { useRef } from 'react';
const order = ['/', '/about', '/work', '/contact'];
export function PageTransition({ children }: { children: React.ReactNode }) {
const pathname = usePathname();
const prev = useRef(pathname);
const dir =
order.indexOf(pathname) > order.indexOf(prev.current) ? 1 : -1;
prev.current = pathname;
return (
({ opacity: 0, x: 40 * d }),
animate: { opacity: 1, x: 0 },
exit: (d: number) => ({ opacity: 0, x: -40 * d }),
}}
initial="initial"
animate="animate"
exit="exit"
transition={{ duration: 0.3, ease: [0.22, 1, 0.36, 1] }}
>
{children}
);
}
```
## Crossfade variant (no mode="wait")
Omit `mode="wait"` so old and new overlap. Stack them absolutely to avoid layout jump.
```tsx
// app/template.tsx
'use client';
import { AnimatePresence, motion } from 'framer-motion';
import { usePathname } from 'next/navigation';
import { FrozenRouter } from './frozen-router';
export default function Template({ children }: { children: React.ReactNode }) {
const pathname = usePathname();
return (
{children}
);
}
```
Wrap the template output's parent in `display: grid` so both stacked children occupy `grid-area: 1 / 1`.
## Shared-element transition (View Transitions API)
Give the same logical element the same `view-transition-name` on both pages; the browser morphs between them.
```tsx
// list page
// detail page
```
```css
::view-transition-old(root),
::view-transition-new(root) { animation-duration: 0.3s; }
/* the named element animates automatically between its two positions */
```
With `next-view-transitions`, use its `` and the morph happens on navigation. Each `view-transition-name` must be unique on the page at a time.
## loading.tsx + transitions
`loading.tsx` shows an instant Suspense fallback during server work. To animate it, make the fallback a motion component; it mounts/unmounts within the same template-driven AnimatePresence flow.
```tsx
// app/work/loading.tsx
'use client';
import { motion } from 'framer-motion';
export default function Loading() {
return (
Loading…
);
}
```
## Reduced-motion
```tsx
'use client';
import { useReducedMotion, motion } from 'framer-motion';
export function PageTransition({ children }: { children: React.ReactNode }) {
const reduce = useReducedMotion();
return (
{children}
);
}
```
For the View Transitions API, gate with CSS:
```css
@media (prefers-reduced-motion: reduce) {
::view-transition-old(root),
::view-transition-new(root) { animation: none; }
}
```
## FrozenRouter import note across versions
The internal context import has shifted across Next versions, e.g.:
```ts
// commonly:
import { LayoutRouterContext } from 'next/dist/shared/lib/app-router-context.shared-runtime';
```
If an upgrade breaks the import, search `node_modules/next/dist/shared/lib/` for `app-router-context` and update the path. Because it is internal, pin awareness of this in any upgrade checklist.
## Framer Motion vs View Transitions decision
| Factor | Framer Motion | View Transitions API |
|---|---|---|
| Browser support | Broad (JS lib) | Uneven; needs fallback |
| Orchestration/stagger | Excellent | Limited |
| Interruptible exits | Yes | Limited |
| Shared element morph | Manual (layoutId) | Native, simple |
| Bundle cost | Adds library | Minimal/native |
| Setup complexity | Medium (FrozenRouter) | Low (next-view-transitions) |
---
Freeze the outgoing route and exit transitions finally fire as intended. Built by **[iart.ai](https://iart.ai/?utm_source=github&utm_medium=readme&utm_campaign=web-animation-skills&utm_content=skill_footer&utm_term=page-transition-animation)** — the AI motion agent for editable, on-brand motion graphics.