Skip to content

Instantly share code, notes, and snippets.

@mfrancois3k
Forked from crevulus/App.tsx
Last active August 16, 2022 20:11
Show Gist options
  • Save mfrancois3k/0b1a0caeaca5ea72d5a9d3033dc6884b to your computer and use it in GitHub Desktop.
Save mfrancois3k/0b1a0caeaca5ea72d5a9d3033dc6884b 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