-
-
Save mfrancois3k/0b1a0caeaca5ea72d5a9d3033dc6884b to your computer and use it in GitHub Desktop.
Basic Page Transition with Framer
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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