aboutsummaryrefslogtreecommitdiffstats
path: root/frontend/src/components/shared/PageTransition.tsx
diff options
context:
space:
mode:
Diffstat (limited to 'frontend/src/components/shared/PageTransition.tsx')
-rw-r--r--frontend/src/components/shared/PageTransition.tsx55
1 files changed, 55 insertions, 0 deletions
diff --git a/frontend/src/components/shared/PageTransition.tsx b/frontend/src/components/shared/PageTransition.tsx
new file mode 100644
index 0000000..fc95865
--- /dev/null
+++ b/frontend/src/components/shared/PageTransition.tsx
@@ -0,0 +1,55 @@
+'use client';
+
+import { motion } from 'framer-motion';
+import { usePathname } from 'next/navigation';
+import { ReactNode, useEffect, useState } from 'react';
+
+interface PageTransitionProps {
+ children: ReactNode;
+}
+
+export function PageTransition({ children }: PageTransitionProps) {
+ const pathname = usePathname();
+ const [isFirstRender, setIsFirstRender] = useState(true);
+
+ useEffect(() => {
+ const timeout = setTimeout(() => {
+ setIsFirstRender(false);
+ }, 500);
+
+ return () => clearTimeout(timeout);
+ }, []);
+
+ const variants = {
+ hidden: { opacity: 0, y: 20 },
+ enter: { opacity: 1, y: 0 },
+ exit: { opacity: 0, y: -20 },
+ };
+
+ // Only apply softer animation on initial render
+ const initialAnimation = isFirstRender ? {
+ initial: { opacity: 0 },
+ animate: { opacity: 1 },
+ transition: { duration: 0.5 }
+ } : {
+ initial: "hidden",
+ animate: "enter",
+ exit: "exit",
+ variants,
+ transition: {
+ type: "tween",
+ ease: "easeInOut",
+ duration: 0.3
+ }
+ };
+
+ return (
+ <motion.div
+ key={pathname}
+ {...initialAnimation}
+ className="w-full h-full"
+ >
+ {children}
+ </motion.div>
+ );
+} \ No newline at end of file