Skip to content

Instantly share code, notes, and snippets.

@crevulus
Last active June 8, 2022 02:04
Show Gist options
  • Save crevulus/f6d232abd937803683208c20580f1194 to your computer and use it in GitHub Desktop.
Save crevulus/f6d232abd937803683208c20580f1194 to your computer and use it in GitHub Desktop.
Basic Page Transition with Framer
import {
AnimatePresence,
m,
LazyMotion,
domAnimation,
domMax
} from "framer-motion";
import type { CSSProperties } from "react";
import { Link, Route, Routes, useLocation } from "react-router-dom";
import "./styles.css";
const styles: Record<string, CSSProperties> = {
page: {
display: "flex",
flexDirection: "column",
justifyContent: "center",
alignItems: "center",
width: "100%",
height: "100vh",
flexGrow: 1
},
page1: {
backgroundColor: "teal"
},
page2: {
backgroundColor: "darkOrchid"
},
copy: {
color: "floralWhite",
fontFamily: "Helvetica"
}
};
const Page1 = () => {
return (
// add strict to prevent motion (m only); import domFeatures (13kb) for use in m components
<LazyMotion features={domAnimation} strict>
{/* // springy/bounced/eased transition because no transition duration */}
<m.div
initial={{ scaleY: 0 }}
animate={{ scaleY: 1 }}
exit={{ scaleY: 0 }}
>
<m.div
style={{ ...styles.page, ...styles.page1 }}
animate={{ scale: 2 }}
transition={{ duration: 0.5, bounce: 0.4, type: "spring" }}
>
<p style={styles.copy}>This is page 1</p>
<Link to="/page2" style={styles.copy}>
Go to Page 2
</Link>
</m.div>
</m.div>
</LazyMotion>
);
};
const Page2 = () => {
return (
// domMax necessary for drag features (but adds 18kb)
<LazyMotion features={domMax} strict>
<m.div
initial={{ scaleY: 0 }}
animate={{ scaleY: 1 }}
exit={{ scaleY: 0 }}
transition={{ duration: 0.5 }} // smooth transition
>
<div style={{ ...styles.page, ...styles.page2 }}>
<m.p
style={styles.copy}
drag
dragConstraints={{
top: -100,
left: 0,
right: 0,
bottom: 100
}}
>
This is page 2
</m.p>
<Link to="/" style={styles.copy}>
Go to Page 1
</Link>
</div>
</m.div>
</LazyMotion>
);
};
export default function App() {
// AnimatePresence listens for changes to direct children. In order to trigger an iupdate of the Routes component (and, therefore, the animation) we need to give it this location data.
const location = useLocation();
return (
// if exitBeforeEnter set to true, AnimatePresence will only render one component at a time
// initial set to false = don't run transition on first load/refresh
<AnimatePresence exitBeforeEnter initial={false}>
<Routes location={location} key={location.pathname}>
<Route path="/" element={<Page1 />} />
<Route path="/page2" element={<Page2 />} />
</Routes>
</AnimatePresence>
);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment