From e1aa422613d50d35c7f7425d5adfb8ea72dc9b9d Mon Sep 17 00:00:00 2001 From: 3zachm <3zachn4@gmail.com> Date: Tue, 13 Dec 2022 00:15:00 -0800 Subject: [PATCH] i finally understand framer --- components/common/NavBar.tsx | 163 ++++++++++++++++++++++------------- layouts/HomeLayout.tsx | 21 ++++- layouts/NavTemplates.tsx | 37 ++++---- pages/index.tsx | 98 +++++++++++++++------ pages/team.tsx | 41 +++++---- 5 files changed, 235 insertions(+), 125 deletions(-) diff --git a/components/common/NavBar.tsx b/components/common/NavBar.tsx index 89f6f4f..97f2906 100644 --- a/components/common/NavBar.tsx +++ b/components/common/NavBar.tsx @@ -8,63 +8,21 @@ interface NavProps { options: NavTemplate[]; } -// nav bar animation, fades in and then animates the children -const containerAnimation: Variants = { - initial: { - opacity: 1, - }, - animate: { - opacity: 1, - transition: { - duration: 2, - delayChildren: 0.5, - staggerChildren: 0.25, - }, - }, -}; - -// default animation for nav bar items -const itemAnimation: Variants = { - initial: { - opacity: 0, - x: 100, - }, - animate: { - opacity: 1, - x: 0, - }, -}; - function NavBar({ options }: NavProps) { const [navList, setNavList] = useState(options); const [isActive, setActive] = useState(false); return ( <m.div className="pointer-events-none fixed inline-grid w-screen grid-cols-2 bg-zinc-900 font-plusJakarta text-2xl lg:grid-cols-3" + variants={containerVariants} initial="initial" animate="animate" - variants={containerAnimation} > <m.div - className="mr-auto flex flex-row items-center justify-center p-2 sm:p-7" - variants={itemAnimation} + className="mr-auto flex flex-row items-center justify-center px-2 pt-5 pb-5 sm:p-7" + variants={itemVariants} > - <m.div - className="ml-4 mr-4 sm:m-0" - initial={{ - scale: 1, - rotate: 0, - }} - animate={{ - scale: 1, - rotate: 360, - transition: { - duration: 4, - type: "spring", - stiffness: 20, - }, - }} - > + <m.div className="ml-4 mr-4 sm:m-0" variants={logoContainerVariants}> <Link key="InvestBotImg" href="/" @@ -87,7 +45,12 @@ function NavBar({ options }: NavProps) { > InvestBot </Link> - <h1 className="flex flex-row items-center justify-center sm:hidden"> + <h1 + className="flex cursor-pointer flex-row items-center justify-center sm:hidden" + onClick={() => { + setActive(!isActive); + }} + > InvestBot </h1> <p className="hidden text-xs text-gray-400 sm:block"> @@ -118,7 +81,7 @@ function NavBar({ options }: NavProps) { </m.div> <m.div className="mr-auto ml-auto hidden flex-row items-center justify-center lg:flex" - variants={itemAnimation} + variants={itemVariants} > {navList.map((nav, index) => ( <Fragment key={index}>{nav.content}</Fragment> @@ -126,7 +89,7 @@ function NavBar({ options }: NavProps) { </m.div> <m.div className="ml-auto flex flex-row items-center justify-center p-2 sm:p-7" - variants={itemAnimation} + variants={itemVariants} > <p className="pointer-events-auto select-none pr-5 text-white"> Login WIP @@ -139,21 +102,20 @@ function NavBar({ options }: NavProps) { // hiddden by default, when active is true, animate in className="pointer-events-auto z-10 flex w-screen flex-col items-center overflow-hidden bg-zinc-800 bg-opacity-70 pt-5 backdrop-blur lg:hidden" // have it take up the entire screen, animate in by expanding from the bottom of the nav bar to the bottom of the screen - // TODO: struggled with getting children staggers/delays to work - initial={{ height: 0 }} - animate={{ height: "100vh" }} - exit={{ height: 0 }} - transition={{ duration: 0.5 }} + variants={mobileContainerVariants} + initial="initial" + animate="animate" + exit="exit" > {navList.map((nav, index) => ( <m.div key={index} - custom={index} - className="pointer-events-auto flex w-[90%] flex-row items-center justify-center border-t-[1px] border-b-[1px] border-zinc-700 p-4" - initial={{ opacity: 0 }} - animate={{ opacity: 1 }} - whileHover={{ backgroundColor: "rgba(0, 0, 0, 0.4)" }} - transition={{ duration: 0.3 }} + className="pointer-events-auto flex w-[90%] flex-row items-center justify-center border-b-[1px] border-zinc-700 p-4" + variants={mobileItemVariants} + whileHover={{ + backgroundColor: "rgba(0, 0, 0, 0.4)", + transition: { duration: 0.2 }, + }} onClick={() => { setActive(false); }} @@ -168,4 +130,85 @@ function NavBar({ options }: NavProps) { ); } +// nav bar animation, fades in and then animates the children +const containerVariants: Variants = { + initial: { + opacity: 1, + }, + animate: { + opacity: 1, + transition: { + duration: 2, + delayChildren: 0.5, + staggerChildren: 0.25, + }, + }, +}; + +// default animation for nav bar items +const itemVariants: Variants = { + initial: { + opacity: 0, + x: 100, + }, + animate: { + opacity: 1, + x: 0, + }, +}; + +// logo animation +const logoContainerVariants: Variants = { + initial: { + scale: 1, + rotate: 0, + }, + animate: { + scale: 1, + rotate: 360, + transition: { + duration: 4, + type: "spring", + stiffness: 20, + }, + }, +}; + +// mobile nav bar container animation +const mobileContainerVariants: Variants = { + initial: { + height: 0, + }, + animate: { + height: "100vh", + transition: { + duration: 0.5, + staggerChildren: 0.15, + }, + }, + exit: { + height: 0, + transition: { + duration: 0.3, + }, + }, +}; + +// mobile nav bar item animation +const mobileItemVariants: Variants = { + initial: { + opacity: 0, + y: -150, + }, + animate: { + opacity: 1, + y: 0, + transition: { + duration: 0.7, + type: "spring", + bounce: 0.3, + }, + }, +}; + export default NavBar; diff --git a/layouts/HomeLayout.tsx b/layouts/HomeLayout.tsx index 8d87cff..8273c0f 100644 --- a/layouts/HomeLayout.tsx +++ b/layouts/HomeLayout.tsx @@ -1,6 +1,12 @@ // Layout/container used for the main mostly empty landing page, can be used for related pages (credits, about, etc.) -import { AnimatePresence, domAnimation, LazyMotion, m } from "framer-motion"; +import { + AnimatePresence, + domAnimation, + LazyMotion, + m, + Variants, +} from "framer-motion"; import Head from "next/head"; import { useRouter } from "next/router"; import NavBar from "../components/common/NavBar"; @@ -44,9 +50,10 @@ function HomeLayout(props: HomeLayoutProps) { <m.div key={router.route.concat("layout-fade")} className="h-screen w-screen" - initial={{ opacity: 0 }} - animate={{ opacity: 1 }} - exit={{ opacity: 0 }} + variants={containerVariants} + initial="initial" + animate="animate" + exit="exit" > {props.children} </m.div> @@ -56,4 +63,10 @@ function HomeLayout(props: HomeLayoutProps) { ); } +const containerVariants: Variants = { + initial: { opacity: 0 }, + animate: { opacity: 1 }, + exit: { opacity: 0 }, +}; + export default HomeLayout; diff --git a/layouts/NavTemplates.tsx b/layouts/NavTemplates.tsx index 612c26c..c15c51e 100644 --- a/layouts/NavTemplates.tsx +++ b/layouts/NavTemplates.tsx @@ -12,21 +12,10 @@ const DefaultNavOption = ({ return ( <Link href={href} key={label} className="w-full text-center"> <m.div - initial={{ - scale: 1, - }} - whileHover={{ - scale: 1.05, - transition: { - duration: 0.2, - }, - }} - whileTap={{ - scale: 0.95, - transition: { - duration: 0.2, - }, - }} + variants={defaultNavVariants} + initial="initial" + whileHover="whileHover" + whileTap="whileTap" > <p className="pointer-events-auto relative select-none pl-3 pr-3 font-plusJakarta text-white md:pl-5 md:pr-5"> {label} @@ -36,6 +25,24 @@ const DefaultNavOption = ({ ); }; +const defaultNavVariants = { + initial: { + scale: 1, + }, + whileHover: { + scale: 1.05, + transition: { + duration: 0.2, + }, + }, + whileTap: { + scale: 0.95, + transition: { + duration: 0.2, + }, + }, +}; + interface NavTemplate { content: ReactComponentElement<any> | ReactElement; } diff --git a/pages/index.tsx b/pages/index.tsx index c90faec..b0866bc 100644 --- a/pages/index.tsx +++ b/pages/index.tsx @@ -84,46 +84,34 @@ const Home: NextPageWithLayout = () => { <div className="inline-grid grid-cols-1 gap-10 text-white md:grid-cols-3"> <m.div className="flex flex-col font-plusJakarta font-semibold md:col-span-2" - initial={{ opacity: 0, y: -100 }} - animate={{ opacity: 1, y: 0 }} - transition={{ - delay: 0.5, - duration: 2.5, - type: "spring", - bounce: 0.5, - stiffness: 150, - }} + variants={sloganContainerVariants} + initial="initial" + animate="animate" > <m.div - className="bg-gradient-to-r from-purple-400 to-pink-600 bg-clip-text text-transparent" - initial={{ opacity: 0 }} - animate={{ opacity: 1 }} - transition={{ delay: 0.5, staggerChildren: 0.2, duration: 1.0 }} + className="bg-gradient-to-r from-purple-400 to-pink-600 bg-clip-text p-2 text-transparent" + variants={sloganHeaderVariants} > - <m.h1 className="text-8xl">Buy high</m.h1> - <m.h1 className="text-8xl">Sell low</m.h1> + <h1 className="text-8xl">Buy high</h1> + </m.div> + <m.div + className="bg-gradient-to-r from-purple-400 to-pink-600 bg-clip-text p-2 text-transparent" + variants={sloganHeaderVariants} + > + <h1 className="text-8xl">Sell low</h1> </m.div> <m.h2 className="pt-2 font-medium italic text-gray-200" - initial={{ opacity: 0 }} - animate={{ opacity: 1 }} - transition={{ delay: 2.5, duration: 1.0 }} + variants={sloganSecondaryVariants} > ...or something like that </m.h2> </m.div> <m.div className="flex items-center justify-center" - initial={{ - opacity: 0, - }} - animate={{ - opacity: 1, - }} - transition={{ - delay: 1.5, - staggerChildren: 0.2, - }} + variants={slideShowVariants} + initial="initial" + animate="animate" > {slideShow} </m.div> @@ -133,6 +121,60 @@ const Home: NextPageWithLayout = () => { ); }; +const sloganContainerVariants = { + initial: { + opacity: 0, + y: -100, + }, + animate: { + opacity: 1, + y: 0, + transition: { + delay: 0.5, + duration: 2.5, + type: "spring", + bounce: 0.5, + stiffness: 150, + delayChildren: 0.5, + staggerChildren: 1.0, + }, + }, +}; + +const sloganHeaderVariants = { + initial: { + opacity: 0, + }, + animate: { + opacity: 1, + }, +}; + +const sloganSecondaryVariants = { + initial: { + opacity: 0, + }, + animate: { + opacity: 1, + transition: { + delay: 3.5, + }, + }, +}; + +const slideShowVariants = { + initial: { + opacity: 0, + }, + animate: { + opacity: 1, + transition: { + delay: 2.0, + duration: 1.0, + }, + }, +}; + // set the layout for the page, this is used to wrap the page in a layout Home.getLayout = function getLayout(page: ReactElement) { return <HomeLayout navOptions={homeMain}>{page}</HomeLayout>; diff --git a/pages/team.tsx b/pages/team.tsx index d65c784..17b023f 100644 --- a/pages/team.tsx +++ b/pages/team.tsx @@ -14,29 +14,13 @@ function Team() { <div className="flex min-h-screen flex-col items-center justify-center py-2"> <m.div className="grid w-[90vw] grid-cols-1 py-2 sm:grid-cols-2 md:grid-cols-4 lg:w-[75vw]" + variants={containerVariants} initial="initial" animate="animate" - variants={containerVariants} - transition={{ - delay: 0.5, - duration: 1.0, - staggerChildren: 0.25, - type: "spring", - bounce: 0.5, - stiffness: 80, - }} > <m.div className="col-span-1 flex w-full items-center justify-center bg-gradient-to-r from-purple-400 to-pink-600 bg-clip-text pt-[200px] pb-[100px] font-plusJakarta text-transparent sm:col-span-2 md:col-span-4" - initial={{ opacity: 0, y: 100 }} - animate={{ opacity: 1, y: 0 }} - transition={{ - delay: 0.5, - duration: 1.0, - type: "spring", - bounce: 0.5, - stiffness: 80, - }} + variants={headerVariants} > <m.h1 className="text-6xl">people</m.h1> </m.div> @@ -104,6 +88,9 @@ const containerVariants: Variants = { duration: 2, delayChildren: 0.5, staggerChildren: 0.25, + type: "spring", + bounce: 0.5, + stiffness: 80, }, }, }; @@ -130,6 +117,24 @@ const rightCardVariants: Variants = { }, }; +const headerVariants: Variants = { + initial: { + opacity: 0, + y: 100, + }, + animate: { + opacity: 1, + y: 0, + transition: { + delay: 0.5, + duration: 1.0, + type: "spring", + bounce: 0.5, + stiffness: 80, + }, + }, +}; + Team.getLayout = function getLayout(page: ReactElement) { return <HomeLayout navOptions={homeMain}>{page}</HomeLayout>; };