"use client";
import { AnimatePresence, motion, useReducedMotion } from "framer-motion";
import { LayoutRouterContext } from "next/dist/shared/lib/app-router-context.shared-runtime";
import { usePathname } from "next/navigation";
import { useContext, useState, type ReactNode } from "react";
/**
* Pins the layout-router context captured when this instance mounted. Each
* keyed page gets its own FrozenRouter, so the *outgoing* page keeps rendering
* its old route data while it animates out.
*/
function FrozenRouter({ children }: { children: ReactNode }) {
const context = useContext(LayoutRouterContext);
const [frozen] = useState(context);
if (!frozen) {
return <>{children}>;
}
return {children};
}
/**
* One unified page transition on every navigation. Lives in the (persistent)
* site layout — NOT in a `template.tsx`, which Next re-creates on each
* navigation and would reset AnimatePresence so nothing animates. The old page
* animates out (rise + blur), then the new page animates in from below.
*/
export function PageTransition({ children }: { children: ReactNode }) {
const reducedMotion = useReducedMotion();
const pathname = usePathname();
return (
{children}
);
}