veza/apps/web/src/components/layout/PageTransition.tsx

42 lines
988 B
TypeScript
Raw Normal View History

import { motion } from 'framer-motion';
import { useLocation } from 'react-router-dom';
import { ReactNode, useMemo } from 'react';
interface PageTransitionProps {
children: ReactNode;
}
/**
* S5.3: Subtile page transitions (Linear-style fade + slide-up)
* Respects prefers-reduced-motion for accessibility.
*/
export function PageTransition({ children }: PageTransitionProps) {
const location = useLocation();
const prefersReducedMotion = useMemo(
() =>
typeof window !== 'undefined' &&
window.matchMedia('(prefers-reduced-motion: reduce)').matches,
[],
);
if (prefersReducedMotion) {
return <div key={location.pathname}>{children}</div>;
}
return (
<motion.div
key={location.pathname}
initial={{ opacity: 0, y: 8 }}
animate={{ opacity: 1, y: 0 }}
exit={{ opacity: 0, y: -8 }}
transition={{
duration: 0.2,
ease: [0.25, 0.1, 0.25, 1],
}}
>
{children}
</motion.div>
);
}