'use client';
import { motion, AnimatePresence } from 'framer-motion';
import { usePathname } from 'next/navigation';
import { useEffect, useState } from 'react';
import { useReducedMotion } from '@/hooks/use-reduced-motion';
const pageVariants = {
initial: {
opacity: 0,
y: 8,
scale: 0.98,
},
animate: {
opacity: 1,
y: 0,
scale: 1,
transition: {
duration: 0.4,
ease: [0.25, 1, 0.5, 1] as const,
staggerChildren: 0.05,
},
},
exit: {
opacity: 0,
y: -8,
scale: 0.98,
transition: {
duration: 0.2,
ease: [0.22, 1, 0.36, 1] as const,
},
},
};
export function PageTransition({ children }: { children: React.ReactNode }) {
const pathname = usePathname();
const shouldReduceMotion = useReducedMotion();
const [mounted, setMounted] = useState(false);
useEffect(() => {
setMounted(true);
}, []);
// SSR 和首次 hydration 阶段直接渲染子内容,避免 framer-motion DOM 差异导致 hydration mismatch
if (!mounted || shouldReduceMotion) {
return <>{children}>;
}
return (