feat: animate page transitions with Motion
This commit is contained in:
Generated
+61
@@ -14,6 +14,7 @@
|
||||
"@tanstack/react-query": "5.101.4",
|
||||
"dayjs": "1.11.23",
|
||||
"i18next": "26.0.2",
|
||||
"motion": "13.2.0",
|
||||
"openapi-fetch": "0.17.0",
|
||||
"openapi-react-query": "0.5.4",
|
||||
"react": "19.2.8",
|
||||
@@ -4921,6 +4922,29 @@
|
||||
"node": ">=18.3.0"
|
||||
}
|
||||
},
|
||||
"node_modules/framer-motion": {
|
||||
"version": "13.2.0",
|
||||
"resolved": "https://registry.npmjs.org/framer-motion/-/framer-motion-13.2.0.tgz",
|
||||
"integrity": "sha512-9E33ebgMaO33w1nN/jEdW8z3/GO483fMi4rqbMG9rt83XgW9QLKRe4NcmJ8s+fQ3O34++UHrIQwlIWGIWTITjA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"motion-dom": "^13.2.0",
|
||||
"motion-utils": "^13.0.0",
|
||||
"tslib": "^2.4.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": "^18.0.0 || ^19.0.0",
|
||||
"react-dom": "^18.0.0 || ^19.0.0"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"react": {
|
||||
"optional": true
|
||||
},
|
||||
"react-dom": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/fsevents": {
|
||||
"version": "2.3.3",
|
||||
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz",
|
||||
@@ -6277,6 +6301,43 @@
|
||||
"node": ">=16 || 14 >=14.17"
|
||||
}
|
||||
},
|
||||
"node_modules/motion": {
|
||||
"version": "13.2.0",
|
||||
"resolved": "https://registry.npmjs.org/motion/-/motion-13.2.0.tgz",
|
||||
"integrity": "sha512-4Hrb5vD6HhjFstLUiCmWvtpsw+WTpP4R+QXfSDYZBz7+uxE/LrRg3aV0ReJxHrTRffHhbIE6svEqnotngXvesQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"framer-motion": "^13.2.0",
|
||||
"tslib": "^2.4.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": "^18.0.0 || ^19.0.0",
|
||||
"react-dom": "^18.0.0 || ^19.0.0"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"react": {
|
||||
"optional": true
|
||||
},
|
||||
"react-dom": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/motion-dom": {
|
||||
"version": "13.2.0",
|
||||
"resolved": "https://registry.npmjs.org/motion-dom/-/motion-dom-13.2.0.tgz",
|
||||
"integrity": "sha512-N6gdSoWRDk0Rh/fVtlqUtLs+fEN3ELFZI3cn3IQE9Mnf3E+Mh8wjO6MstzCOPFh4Yf0L1as5m2eUyYWj8ylVSQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"motion-utils": "^13.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/motion-utils": {
|
||||
"version": "13.0.0",
|
||||
"resolved": "https://registry.npmjs.org/motion-utils/-/motion-utils-13.0.0.tgz",
|
||||
"integrity": "sha512-7DnN7TmbLcYXcG4RVadXIihWlyuM9afoUww8Y5Agg431kGKiuL2/OMyP4mJ5wLz+pvN3t5ySClLOaVXJ+wekRQ==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/ms": {
|
||||
"version": "2.1.3",
|
||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
|
||||
|
||||
@@ -36,6 +36,7 @@
|
||||
"@tanstack/react-query": "5.101.4",
|
||||
"dayjs": "1.11.23",
|
||||
"i18next": "26.0.2",
|
||||
"motion": "13.2.0",
|
||||
"openapi-fetch": "0.17.0",
|
||||
"openapi-react-query": "0.5.4",
|
||||
"react": "19.2.8",
|
||||
|
||||
@@ -2,6 +2,7 @@ import { Container, Group, Skeleton, Stack } from "@mantine/core";
|
||||
import type { FC, PropsWithChildren } from "react";
|
||||
import { Suspense } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { RouteTransition } from "./RouteTransition";
|
||||
|
||||
type RouteSkeletonVariant = "auth" | "content" | "shell";
|
||||
type LazyPageProps = PropsWithChildren<{ variant: RouteSkeletonVariant }>;
|
||||
@@ -60,7 +61,11 @@ const LazyPage: FC<LazyPageProps> = (props) => {
|
||||
const { children, variant } = props;
|
||||
return (
|
||||
<Suspense fallback={<RouteSkeleton variant={variant} />}>
|
||||
{children}
|
||||
{variant === "shell" ? (
|
||||
children
|
||||
) : (
|
||||
<RouteTransition>{children}</RouteTransition>
|
||||
)}
|
||||
</Suspense>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
import { domAnimation, LazyMotion, useReducedMotion } from "motion/react";
|
||||
import * as m from "motion/react-m";
|
||||
import type { FC, PropsWithChildren } from "react";
|
||||
import { useLocation } from "react-router";
|
||||
|
||||
const RouteTransition: FC<PropsWithChildren> = (props) => {
|
||||
const { children } = props;
|
||||
const { pathname } = useLocation();
|
||||
const reduceMotion = useReducedMotion();
|
||||
|
||||
return (
|
||||
<LazyMotion features={domAnimation}>
|
||||
<m.div
|
||||
key={pathname}
|
||||
initial={reduceMotion ? false : { opacity: 0 }}
|
||||
animate={{ opacity: 1 }}
|
||||
transition={{ duration: reduceMotion ? 0 : 0.2, ease: "easeOut" }}
|
||||
>
|
||||
{children}
|
||||
</m.div>
|
||||
</LazyMotion>
|
||||
);
|
||||
};
|
||||
|
||||
export { RouteTransition };
|
||||
Reference in New Issue
Block a user