i finally understand framer
This commit is contained in:
parent
2642cf0599
commit
e1aa422613
5 changed files with 235 additions and 125 deletions
|
@ -8,63 +8,21 @@ interface NavProps {
|
||||||
options: NavTemplate[];
|
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) {
|
function NavBar({ options }: NavProps) {
|
||||||
const [navList, setNavList] = useState(options);
|
const [navList, setNavList] = useState(options);
|
||||||
const [isActive, setActive] = useState(false);
|
const [isActive, setActive] = useState(false);
|
||||||
return (
|
return (
|
||||||
<m.div
|
<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"
|
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"
|
initial="initial"
|
||||||
animate="animate"
|
animate="animate"
|
||||||
variants={containerAnimation}
|
|
||||||
>
|
>
|
||||||
<m.div
|
<m.div
|
||||||
className="mr-auto flex flex-row items-center justify-center p-2 sm:p-7"
|
className="mr-auto flex flex-row items-center justify-center px-2 pt-5 pb-5 sm:p-7"
|
||||||
variants={itemAnimation}
|
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
|
<Link
|
||||||
key="InvestBotImg"
|
key="InvestBotImg"
|
||||||
href="/"
|
href="/"
|
||||||
|
@ -87,7 +45,12 @@ function NavBar({ options }: NavProps) {
|
||||||
>
|
>
|
||||||
InvestBot
|
InvestBot
|
||||||
</Link>
|
</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
|
InvestBot
|
||||||
</h1>
|
</h1>
|
||||||
<p className="hidden text-xs text-gray-400 sm:block">
|
<p className="hidden text-xs text-gray-400 sm:block">
|
||||||
|
@ -118,7 +81,7 @@ function NavBar({ options }: NavProps) {
|
||||||
</m.div>
|
</m.div>
|
||||||
<m.div
|
<m.div
|
||||||
className="mr-auto ml-auto hidden flex-row items-center justify-center lg:flex"
|
className="mr-auto ml-auto hidden flex-row items-center justify-center lg:flex"
|
||||||
variants={itemAnimation}
|
variants={itemVariants}
|
||||||
>
|
>
|
||||||
{navList.map((nav, index) => (
|
{navList.map((nav, index) => (
|
||||||
<Fragment key={index}>{nav.content}</Fragment>
|
<Fragment key={index}>{nav.content}</Fragment>
|
||||||
|
@ -126,7 +89,7 @@ function NavBar({ options }: NavProps) {
|
||||||
</m.div>
|
</m.div>
|
||||||
<m.div
|
<m.div
|
||||||
className="ml-auto flex flex-row items-center justify-center p-2 sm:p-7"
|
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">
|
<p className="pointer-events-auto select-none pr-5 text-white">
|
||||||
Login WIP
|
Login WIP
|
||||||
|
@ -139,21 +102,20 @@ function NavBar({ options }: NavProps) {
|
||||||
// hiddden by default, when active is true, animate in
|
// 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"
|
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
|
// 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
|
variants={mobileContainerVariants}
|
||||||
initial={{ height: 0 }}
|
initial="initial"
|
||||||
animate={{ height: "100vh" }}
|
animate="animate"
|
||||||
exit={{ height: 0 }}
|
exit="exit"
|
||||||
transition={{ duration: 0.5 }}
|
|
||||||
>
|
>
|
||||||
{navList.map((nav, index) => (
|
{navList.map((nav, index) => (
|
||||||
<m.div
|
<m.div
|
||||||
key={index}
|
key={index}
|
||||||
custom={index}
|
className="pointer-events-auto flex w-[90%] flex-row items-center justify-center border-b-[1px] border-zinc-700 p-4"
|
||||||
className="pointer-events-auto flex w-[90%] flex-row items-center justify-center border-t-[1px] border-b-[1px] border-zinc-700 p-4"
|
variants={mobileItemVariants}
|
||||||
initial={{ opacity: 0 }}
|
whileHover={{
|
||||||
animate={{ opacity: 1 }}
|
backgroundColor: "rgba(0, 0, 0, 0.4)",
|
||||||
whileHover={{ backgroundColor: "rgba(0, 0, 0, 0.4)" }}
|
transition: { duration: 0.2 },
|
||||||
transition={{ duration: 0.3 }}
|
}}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
setActive(false);
|
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;
|
export default NavBar;
|
||||||
|
|
|
@ -1,6 +1,12 @@
|
||||||
// Layout/container used for the main mostly empty landing page, can be used for related pages (credits, about, etc.)
|
// 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 Head from "next/head";
|
||||||
import { useRouter } from "next/router";
|
import { useRouter } from "next/router";
|
||||||
import NavBar from "../components/common/NavBar";
|
import NavBar from "../components/common/NavBar";
|
||||||
|
@ -44,9 +50,10 @@ function HomeLayout(props: HomeLayoutProps) {
|
||||||
<m.div
|
<m.div
|
||||||
key={router.route.concat("layout-fade")}
|
key={router.route.concat("layout-fade")}
|
||||||
className="h-screen w-screen"
|
className="h-screen w-screen"
|
||||||
initial={{ opacity: 0 }}
|
variants={containerVariants}
|
||||||
animate={{ opacity: 1 }}
|
initial="initial"
|
||||||
exit={{ opacity: 0 }}
|
animate="animate"
|
||||||
|
exit="exit"
|
||||||
>
|
>
|
||||||
{props.children}
|
{props.children}
|
||||||
</m.div>
|
</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;
|
export default HomeLayout;
|
||||||
|
|
|
@ -12,21 +12,10 @@ const DefaultNavOption = ({
|
||||||
return (
|
return (
|
||||||
<Link href={href} key={label} className="w-full text-center">
|
<Link href={href} key={label} className="w-full text-center">
|
||||||
<m.div
|
<m.div
|
||||||
initial={{
|
variants={defaultNavVariants}
|
||||||
scale: 1,
|
initial="initial"
|
||||||
}}
|
whileHover="whileHover"
|
||||||
whileHover={{
|
whileTap="whileTap"
|
||||||
scale: 1.05,
|
|
||||||
transition: {
|
|
||||||
duration: 0.2,
|
|
||||||
},
|
|
||||||
}}
|
|
||||||
whileTap={{
|
|
||||||
scale: 0.95,
|
|
||||||
transition: {
|
|
||||||
duration: 0.2,
|
|
||||||
},
|
|
||||||
}}
|
|
||||||
>
|
>
|
||||||
<p className="pointer-events-auto relative select-none pl-3 pr-3 font-plusJakarta text-white md:pl-5 md:pr-5">
|
<p className="pointer-events-auto relative select-none pl-3 pr-3 font-plusJakarta text-white md:pl-5 md:pr-5">
|
||||||
{label}
|
{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 {
|
interface NavTemplate {
|
||||||
content: ReactComponentElement<any> | ReactElement;
|
content: ReactComponentElement<any> | ReactElement;
|
||||||
}
|
}
|
||||||
|
|
|
@ -84,46 +84,34 @@ const Home: NextPageWithLayout = () => {
|
||||||
<div className="inline-grid grid-cols-1 gap-10 text-white md:grid-cols-3">
|
<div className="inline-grid grid-cols-1 gap-10 text-white md:grid-cols-3">
|
||||||
<m.div
|
<m.div
|
||||||
className="flex flex-col font-plusJakarta font-semibold md:col-span-2"
|
className="flex flex-col font-plusJakarta font-semibold md:col-span-2"
|
||||||
initial={{ opacity: 0, y: -100 }}
|
variants={sloganContainerVariants}
|
||||||
animate={{ opacity: 1, y: 0 }}
|
initial="initial"
|
||||||
transition={{
|
animate="animate"
|
||||||
delay: 0.5,
|
|
||||||
duration: 2.5,
|
|
||||||
type: "spring",
|
|
||||||
bounce: 0.5,
|
|
||||||
stiffness: 150,
|
|
||||||
}}
|
|
||||||
>
|
>
|
||||||
<m.div
|
<m.div
|
||||||
className="bg-gradient-to-r from-purple-400 to-pink-600 bg-clip-text text-transparent"
|
className="bg-gradient-to-r from-purple-400 to-pink-600 bg-clip-text p-2 text-transparent"
|
||||||
initial={{ opacity: 0 }}
|
variants={sloganHeaderVariants}
|
||||||
animate={{ opacity: 1 }}
|
|
||||||
transition={{ delay: 0.5, staggerChildren: 0.2, duration: 1.0 }}
|
|
||||||
>
|
>
|
||||||
<m.h1 className="text-8xl">Buy high</m.h1>
|
<h1 className="text-8xl">Buy high</h1>
|
||||||
<m.h1 className="text-8xl">Sell low</m.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.div>
|
||||||
<m.h2
|
<m.h2
|
||||||
className="pt-2 font-medium italic text-gray-200"
|
className="pt-2 font-medium italic text-gray-200"
|
||||||
initial={{ opacity: 0 }}
|
variants={sloganSecondaryVariants}
|
||||||
animate={{ opacity: 1 }}
|
|
||||||
transition={{ delay: 2.5, duration: 1.0 }}
|
|
||||||
>
|
>
|
||||||
...or something like that
|
...or something like that
|
||||||
</m.h2>
|
</m.h2>
|
||||||
</m.div>
|
</m.div>
|
||||||
<m.div
|
<m.div
|
||||||
className="flex items-center justify-center"
|
className="flex items-center justify-center"
|
||||||
initial={{
|
variants={slideShowVariants}
|
||||||
opacity: 0,
|
initial="initial"
|
||||||
}}
|
animate="animate"
|
||||||
animate={{
|
|
||||||
opacity: 1,
|
|
||||||
}}
|
|
||||||
transition={{
|
|
||||||
delay: 1.5,
|
|
||||||
staggerChildren: 0.2,
|
|
||||||
}}
|
|
||||||
>
|
>
|
||||||
{slideShow}
|
{slideShow}
|
||||||
</m.div>
|
</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
|
// set the layout for the page, this is used to wrap the page in a layout
|
||||||
Home.getLayout = function getLayout(page: ReactElement) {
|
Home.getLayout = function getLayout(page: ReactElement) {
|
||||||
return <HomeLayout navOptions={homeMain}>{page}</HomeLayout>;
|
return <HomeLayout navOptions={homeMain}>{page}</HomeLayout>;
|
||||||
|
|
|
@ -14,29 +14,13 @@ function Team() {
|
||||||
<div className="flex min-h-screen flex-col items-center justify-center py-2">
|
<div className="flex min-h-screen flex-col items-center justify-center py-2">
|
||||||
<m.div
|
<m.div
|
||||||
className="grid w-[90vw] grid-cols-1 py-2 sm:grid-cols-2 md:grid-cols-4 lg:w-[75vw]"
|
className="grid w-[90vw] grid-cols-1 py-2 sm:grid-cols-2 md:grid-cols-4 lg:w-[75vw]"
|
||||||
|
variants={containerVariants}
|
||||||
initial="initial"
|
initial="initial"
|
||||||
animate="animate"
|
animate="animate"
|
||||||
variants={containerVariants}
|
|
||||||
transition={{
|
|
||||||
delay: 0.5,
|
|
||||||
duration: 1.0,
|
|
||||||
staggerChildren: 0.25,
|
|
||||||
type: "spring",
|
|
||||||
bounce: 0.5,
|
|
||||||
stiffness: 80,
|
|
||||||
}}
|
|
||||||
>
|
>
|
||||||
<m.div
|
<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"
|
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 }}
|
variants={headerVariants}
|
||||||
animate={{ opacity: 1, y: 0 }}
|
|
||||||
transition={{
|
|
||||||
delay: 0.5,
|
|
||||||
duration: 1.0,
|
|
||||||
type: "spring",
|
|
||||||
bounce: 0.5,
|
|
||||||
stiffness: 80,
|
|
||||||
}}
|
|
||||||
>
|
>
|
||||||
<m.h1 className="text-6xl">people</m.h1>
|
<m.h1 className="text-6xl">people</m.h1>
|
||||||
</m.div>
|
</m.div>
|
||||||
|
@ -104,6 +88,9 @@ const containerVariants: Variants = {
|
||||||
duration: 2,
|
duration: 2,
|
||||||
delayChildren: 0.5,
|
delayChildren: 0.5,
|
||||||
staggerChildren: 0.25,
|
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) {
|
Team.getLayout = function getLayout(page: ReactElement) {
|
||||||
return <HomeLayout navOptions={homeMain}>{page}</HomeLayout>;
|
return <HomeLayout navOptions={homeMain}>{page}</HomeLayout>;
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in a new issue