Awwwards Rebuilt Mini | Building a Hamburger Menu using Gatsby and Framer Motion

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
hope everyone's off to a wonderful day my name is akrom khalid and in today's episode we're going to take the time to figure out how we can build a really nice animation for a hamburger menu using framer motion and gas bjs now the gatsby part isn't too complicated we're going to be using it to create some dynamic page routing uh using the create pages method that comes with gatsby so it is a very simple process to get dynamic pages in terms of the data it is static data so we're not going to be connected to a database or a cms or anything like that we're primarily focusing our efforts to create this hamburger menu that you see on the screen right now the process behind it is it has these two panels that come up it's a really cool animation when you hover on it it's pretty interactive and it kind of calls for a bit of you know cool page transitions when you're jumping from route to route in your hamburger menu before i head out make sure you leave a like and don't forget to subscribe share it with friends and family whoever is really interested in front end and also leave a comment in terms of what you would like to see in the future i am trying to kind of push the boundaries for this channel to create more high quality videos and if you want to support the channel i do have a patreon link down below um so check that out take care guys now to get things started i already have the starter branch cloned and it is right here on the screen if we take a look at the localhost 8000 running the starter branch you'll see that you have just the header a little message that tells you to click on the menu button and if you click on the menu button nothing actually happens i do have the final project on a netify hosting so if we just go back home i'll have this link the description as the final product so you could definitely just play around with it and mess with it if you want but we're not focusing our efforts here we're going to be starting on the starter branch so again make sure you head over to the github repo and clone the starter so that we can get started to break down the architecture real quick what i do have is inside my source folder i do have a components folder which in the components folder just houses the different components we're going to build right now there is a header js a layout.js seo js which this doesn't really matter to us all that much this is just comes with gatsby when you just get the gatsby starter if we close out of that we do have gatsby images and for gatsby images i am using the gatsby image and specifically what i'm doing here is i'm querying for four different images and then at the bottom depending on the prop source we pass to our image we're going to render out the different images so this is just a quick way to render out four outcomes of a different image using the gatsby image without needing to necessarily make several gatsby image components and we'll get to that later in the video outside of the component we have a data and this is just products.json file and it's just going to house information related to our products you can see that we have our new balance our air max our air max off-whites typically this will come from a database or if you're hooking up to a cms this is where all the data is coming from holy my voice but we're just using a json file we're not hooking anything up uh to a back end or anything like that so this will just be dummy data for us and then with our icons we have icons js which is just returning a close icon as a react component and then for our images we just have our images where the shoes live as well as our favicon finally we do have pages which is an index.js and a 404 and xjs is returning that click on the menu button and then for our styles we have the app sas a normalized sas a variable sas and then for the components nested in our styles folder we do have banner sas and header sas we don't have any styles for our menu or our mini component built out yet and we'll do that together so we'll close out of the styles folder one thing i do want to mention is if we head over to our package json and let's look for layout uh so i i did install the gatsby plugin layout and the gatsby plugin layout pretty much just allows us to not need to reference the layout uh component in every single page we build so you can see that if we open up index.js and then go to our components and open up layout.js layout.js is wrapping our children which would be everything inside of our pages folder typically if you're not using the gatspeed layout plugin or the gatsby plugin layout whichever whichever one it is you'll then need to write layouts as the parent like so every single time you oops every single time you create a page but using that plugin just allows us to avoid that and it will wrap it in the gatsby browser you can also use kind of state within your gatsby browser if you want but just installing that plug-in allows us to do it without needing to write layout every single time so enough rambling let's go ahead and actually get started the very first thing we are going to do is we're going to set up the product page as well as the routing inside gatsby node js so inside guess you know js this is where we'll kind of be able to create the products page as well as passing a parameter to the different titles or different names so to do that what we're doing here is just using gatsby node.js first and what we're gonna do is write the following exports dot create pages and we're going to pass in a function with the following so pass actions it's going to represent the create pages and then make it an arrow function and then we'll return the following so for me to describe create pages real quick pretty much gatsby allows us to access different apis and one of the apis is create pages and what it does is it allows us to add pages within our pages folder without needing to create those pages so reading the definition uh straight from the gatsby website it tells plugins to add pages this extension point to this extension point is called only after the initial sourcing and transformations of node plus creation of the graphql schema are comp are complete so you can query your data in order to create pages pretty much as we're querying our data depending on the different data we have currently we have four endpoints it will create pages based off those endpoints so when you're creating a blog you have blog posts you don't create blog posts every single time you want to create a post you you create pages or you pass this function to create those pages and pass in the dynamic data so to continue on if we want to query that data we're not going to use graphql to query the data since we're just using static data that we have in our data folder what i'll do is just require that data so we'll do source data for slash product dot json and now this product is going to retrieve all of the data we have and then next we're going to use a for each array method to create a new page for each individual data point or endpoint so we'll use products.for each and then we'll just pass product and pass in an arrow function and then here we'll pass the create pages and inside create pages we're going to pass different configuration options and so the following would be this the path that we're going to actually create for this will be forward slash product and then forward slash and we'll use a template literal we'll do product dot id now this product dot id is coming directly from our data the products json so the id is just going to be kind of like our parameter or our url so we do have the dashes that represent kind of spaces so that's going to be our path next for our component the component we're going to want to load or mount for each page is going to be the following so we'll require dot resolve and we'll need to create sort of like a template so we'll do source we'll just call this templates forward slash product.js finally for our context so that we can access the data we'll just simply pass product which is going to return the entire object for each of our endpoints so we'll go ahead and save this what we'll need to do next is actually build out the product page so inside our source folder we'll create a new folder and we'll call this templates and inside templates we'll create a new file and we'll call it product.js inside product.js we'll write r-a-f-e where we're going to create a component and just make sure you capitalize product next what we're going to do is just build out that product page real quick so for our first div we'll give it a class name of banner and then inside banner we'll give it a class name of inner banner and then inside of that we'll give a container and now additional to the container we're going to give it a fluid class then we're going to have an h1 with the class name of main dash headline and inside main headline what we'll do is just we'll say hello for now let's save that let's go back to our project real quick and then because we did edit that node file the gatsby node.js we do need to restart the development process so it does give us a alert to do that and we can just hit ok and i wonder if it restarts it by itself let's check out the console let's refresh okay i guess it did so what we could do is we do localhost four slash and i have this saved before so we do product forward slash air max 90 and it gives us an error it says it typically is an issue a current building component for that path okay and i wonder if it even restarted the development process so we can manually restart real quick okay so we did get an error uh products is not defined and that's because in our gatsby node i created a variable for product but then i am looping through products which doesn't exist so to fix the issue what we'll need to do is just match the variable to what we call here so it's products let's go ahead and write products and another thing i'm looking at is the create pages this should only say create page so let's get rid of the two s's uh where we use create pages or create page and then we actually call the function create page or the method let's actually fix that so we're ex exports that create pages with an s and then using create page is going to be singular and not create pages so let's go ahead and get rid of those two s's as well as and add an s to our products variable uh let's save that and then if we head back to our browser it will say that it needs to rebuild the development process so we can say okay and then this should rebuild our project i wonder if it's actually rebuilding though i'm still getting that error okay i guess you can just do it manually because when you when it asks you to rebuild you'll click rebuild and it'll give you like a message saying gatsby's rebuilding or something like that uh but it's not giving me that so we'll just manually rebuild it and then once this is done we can just refresh the page that we're on okay so it's done and i don't see any errors let's go back to our project and refresh and then you can see that we are getting that hello message which is perfect and if we go to our product json and get a new id or sorry we already have air max 90s let's do new balance x90 you'll still get hello because that is just the default message that we're sending here to change that and make it dynamic uh what we'll do is we will then grab the page context and then um then we can just kind of loop through the data that we pass through this or is that through this context so what we'll do here is in product we'll grab page context and then inside of our components we'll create a variable for product and we'll set product equal to page context and then if we want to make this dynamic now what we'll do is write product dot title and then this will return the title uh for our uh different pages that we have so we have air max 90 new balance x90 and air max 97 off whites so now that we're returning the title uh the title should get updated here and if we change this to the air max 90 it will be updated to air max 90. we'll want to do the image as well so right here is where we're going to use that gatsby image so we'll say image source and the source we're going to pass for our image is product dot source which product dot source is going to return a number uh if we remember here source just one two three and then we'll then in the gatsby image component return the different sources of images that we have so to use that we'll do import image and we'll import image from the following so it's going to be in components gatsby images and just an image oops let's go ahead and save that and then if we take a look uh you can see that we have our image in the background um i don't think it should be in the background i think we're missing a div here but you know what i kind of like in the background i'm not gonna lie um if we switch it to new balance x90 look at the new balancex 90s you know what i mean after now i'm not i'm rebuilding it for the tutorial having it as a full background is actually pretty neat we just might need to make up for the dark text or dark image but i think we'll take a look at that towards the end to see if it looks better but for now what we'll do is create an image div and pass in the gatsby image within that image div to adjust the widths and center it along our container so we've got the pages build out and then the different pages do work so if we switch to the yeezy 700 geode i think that's a geode i don't know uh if we switch to that screen you can see that it is picking up the different pages and it's building or creating those pages for us which is perfect so that's step one done step two was building up the product template which we just did so we've got step one done which is setting up the routing and gatsby node.js step two would be build the product template pages and the styles are already made so we don't need to waste too much time on the styles next we're going to build the menu as jsx as well as its styles then we'll transition over to toggling it and locking the background for when the menu is active so let's go ahead and do that in part 2. so next we're going to go ahead and build out the menu component as well as its styling so let's focus on that now one thing i do need to mention is this is not responsive so if you're working on different screens the layout might be a bit different the idea here is just to learn how to use framer motion as well as gatsby for its different page transitions don't worry too much on styling or responsiveness if you want to do that just spend some time there on your own but to carry on we'll go ahead and open up the let's close these out we'll go ahead and open up the components folder and inside the components folder we'll create a menu.js now inside menu js we'll do rafce so that we can create a react component and then let's go ahead and capitalize menu the very first div that we're going to create will be called projects so the class name will say projects now inside projects we have a menu title so i'll create a div with the class name of menu title and we'll call this products and looking at this now i wonder why i named projects and products i think we should just call the top one products i don't know it's up to you really um content doesn't really matter right now next what we're going to do is create a div with the class name of close which will represent the close icon and so inside the close icon we are going to write a close component and this close component is going to be coming from our icons folder so to import that we're going to do import close from and then we'll go to components actually it's not on components forward slash or is that icons forward slash icons this will then bring in the close icon now next what we're working on is the menu itself with all the list items so we'll say a class name with menu inside menu we do have a container and inside the container we have a menu dash enter and let me close the console just to create more space for us now inside the menu enter what we're going to have here is a unordered list so we'll say ul and now inside the unordered list we'll have a list item so each list item will represent an individual row what i'm going to do here is build that one list item and then we'll loop in the data to build out the rest rather than needing to copy and paste four different times for our list items so i'll go ahead and build the first one so it's going to be a list item and inside the list item we'll have a link for our gatsby link now the to prop for our gatsby link is going to take us to this so it's going to be for slash product for slash and then we'll use a template literal for our id but since we're not passing in id just yet um i'll go ahead and just put an a and we'll get back to that one here in a second once we start passing the data now inside the link we're going to have a wrapper and inside this wrapper what we're going to do is first create that line that's going to be on the left and the line is going to be on the right and to better represent this i think i should just pull up the side itself if we open up the menu uh what line is going to represent is these lines so we have one on the right and then we have one on the left so you can see that they are going to receive different classes using flexbox and they'll be you know they'll just look a bit different in terms of the widths so we can define that as we build the styles so the first one is going to be a class of line and then we're going to pass it left so that we can kind of define it that it's going to be on the left side now when it comes to animating we are going to pass a class name of mask inside of it and what mask is going to do is let me close this and reopen it mask will give it that effect of it revealing my god i got in the way but if you look at the lines you can see that they are kind of uh revealing themselves and it's not a width right the width is not going from 0 to 800 what's happening is that we have a mask overlay of a white box that's just changing its widths revealing the line behind it so that is what mask will represent for now we'll just pass in a mask and not do anything to it right now but when it comes to animating we'll adjust and i wonder if it might throw us off we might need to comment this out we'll just comment it out for now now as a sibling to the line left what we'll have is a title and inside title we have an h2 and we'll just pass in title for now and like i mentioned regarding the mask on the line left uh what you'll see is when we open this up you can see the title going up and it's not fading in as an opacity but it's just like sliding up so it does have a mask itself so inside the h2 what i'm going to do is pass in a div with the class name of text and this will kind of represent the text so that it could kind of go up while it's hiding behind the title and or h2 now as a sibling to our title what we're going to have is a thumbnail so we'll say thumbnail an inside thumbnail will pass in a gatsby image so we'll say image and for now our source will just be one and we'll update all this to be dynamic once we start mapping through the data so thumbnail is going to represent the following which is this right here so this will just be thumbnail and then when we hover we have a floating image which will build out in a second again thumbnail is just the small images that is in our list item so we're building thumbnail we pass in an image here thumbnail will also get a mask so what i'll do is create a mask and just comment that out when it comes time to animating now as a sibling to our thumbnail what we have is the floating image which i just talked about so we have floating dash image and inside floating image we also have a gatsby image so we're gonna have image source one now to finally top off everything inside our wrapper we are going to have a line we'll just copy the line that we built up here the only difference here though is this is going to represent our right line and we also want to add a right class for our mask itself perfect so let's go ahead and save that and then what we could do is let's display this in our layout so if we switch over to our layout.js underneath the header we'll go ahead and import menu and we'll import this from our menu and then underneath header we can just bring in menu like so now it's not going to look pretty at all in fact if we take a look we do have an error which says link is not defined image is not defined and inside our menu js let's go ahead and define those so we'll import link and we'll import this from gatsby and then we also need to import image i'll make a comment for gatsby image we'll import the following so image will come from the slash components four slash gatsby images first last image so let's take a look now um okay perfect so you can see that we have the product um header the close button we have the title which says products i think it's supposed to say something else no oh yeah the title right here we'll switch the title to say air max what is it air max 90 i don't know what it is exactly so we'll say that this is the title this is the thumbnail and then this is the floating image so that is our menu right here we'll start working on styles uh so let's go ahead and open up our styles folder inside the components we'll create a new file and we'll call this menu.scss and then we also need to make sure we import that so let's go ahead and import the following four slash components or slash menu dot scss don't forget to add the colon at the end okay perfect so let's go to menu scss and start working on the styles off the top we do have products which is our parent and let me actually split this so if we put these into do two different screens and then open up menu.js we could start seeing let's hit command b let's get rid of that on the left but we could see how to actually start nesting so products is the top uh parent oopsie and now inside products we have the dot close and dot close and menu title is actually going to get very similar styles so we'll say dot close and menu title menu title will be slightly different so we'll pass in menu title by itself as well so close menu title will have similar styles but the menu title will be a bit different now outside of those but still being inside the product we have a menu and inside menu we have menu dash enter regarding our container we do have the container defined within our app so these are just default styles that i already have that we don't need to worry about let's close that now inside our menu enter we have an unordered list inside the unordered list list we have an li and inside that we have an a tag which a tags represent the link next we have a wrapper inside the wrapper we have a title and inside the title we have an h2 now as a sibling to the title but still being inside the wrapper uh what we have next is a thumbnail and now inside that thumbnail we do have that mask which we'll get to when we start animating and as a sibling to that we do have our image which represents the gatsby image as a sibling to the thumbnail what we have next is the floating image so we have floating dash image what we're moving on to is outside of the wrapper um outside of this wrapper what we're gonna do is work on our line so we'll have a dot line um there's a lot that goes with this line which i need to cover but right now we'll just say dot mask and we'll get to the styles in a sec so go ahead and save that and that is our entire schema uh we'll go ahead and start styling now starting at the very top of products at the very top we're going to set the position to a position of fixed um and what i'll do is get rid of the split screen because we don't need the left anymore so we need to focus here uh position fixed the height will be set to 100 percent the width will be set to 100 our z index is going to be set to nine our overflow will be hidden and then our background is going to be white now you could use the variables that i have or you could just use the hex codes it's really up to you so if we take a look at what it looks like now that's not what it looks like it looks like this you can see the background is completely covered we no longer see the header and that menu button z index thousand um what am i doing close okay yeah so we're working on the clothes in the menu title um this is very exaggerated you don't need to set a thousand i'll set a thousand because i do want this to be the highest for our menu title and our close button but it doesn't need to be that much we can adjust it later our position will be set to absolute our color is going to be black the top is going to be set to 3ram and for our rims our default is 16 pixels so when you're using rams they're relative to whatever the html font size is so if you're using 16 16 x 3 i'm not good at math 48 or 52 6 something um right will be set to 5.8 rim not four but 5.8 ram our display is going to be set to flex we're going to align the items to center and then the text transform we're going to set this to an uppercase finally we have the font size which font size will be 8.75 rim which this ultimately equals to around 14 pixels and then we do have letter spacing which our letter spacing is going to be 0.05 rim and then our cursor we'll set that to pointer and then our svg what we'll do is nest the menu title within the svg or sorry the close button within the svg and we'll give that a height of 30 pixels the svg is going to represent our close button but if we take a look now you can see on the top right we have the x button as well as the products so we'll adjust products to have it on the far left which is our menu title and that is why we have menu title right here to adjust that so our top will be set to 3ram our left will be 5.8 rem and then our font size we'll go ahead and set that to 1.4 rem and save that so that's going to move it to the far left and if you want to capitalize it that's really up to you i did realize i put text transform here but we could get rid of that and it will be lower case also what do we need font size for for the icon if we're defining the height this is just sloppy code on my half my behalf perfect so we've got the products as well as the x button laid out let's start focusing on everything else next we can focus on the menu itself the menu is going to receive a height of 100 viewport height and then our menu enter will have a display set to flex our flex direction will be column our justify content will be center we're aligning the items to center as well and then we're giving it a padding of eight rim off the top and zero on the left and right we also need to give it a height that will match the menu so we could say 100 percent or 100 v port height i'll go ahead and say 100 v port height now this will adjust it and add it some padding and center everything in the middle next we have our unordered list we'll give this a width of 100 percent and we'll say display block for our list items will give us a position of relative a width of 100 percent as well as a height set to 115 pixels now i jump back and forth between pixels and ram typically if we're talking about i don't know best practices you might want to stick with one but breaking rules is fun so it doesn't really matter next we have the height which the height of the a tag or the link is going to be 100 which will ultimately equal the 100 of the height of 115 pixels now inside the wrapper we also have a height of 100 our display will be set to flex and what we're doing is aligning items to the bottom so flex end let's save this and take a look you can see that we have the air max aligned the images are nowhere to be found and that's because we need to define their heights which we'll do in a minute next we have the title now the title is going to receive a margin of zero and one rim on the left and right and then for our h2 we're going to give it an overflow of hidden a margin of zero because i do believe it comes default in the app sas giving it margin our font size we're going to edit this to forum our font weight will be set to 500. let's save that so it just increases the size of it which looks good next we can jump to our thumbnail for our thumbnail what we're doing is having a margin bottom of 1.4 rim our overflow will be set to hidden our position will be set to absolute our left will be 30 ram our width will be 7.6 rim oops our height will be set to 5 we can skip the mask for now but we can start working on the image the image is going to have a position of absolute our width will be set to 100 percent and our height will equal that which is 100 finally we'll just set a right of zero let's take a look now and there's an issue we've got to add a colon at the end of width so now we have our thumbnail laid out beautifully let's keep going we don't need to stop next we do have our floating image now the floating image isn't going to present itself unless we hover on the title uh that comes with animating but we'll go ahead and display it here and then just hide it so the pointer events on this one is going to be set to none and the reason we're setting a pointer event of none is the following if we look at our project here you can see that if i hover off air max then it stops the effect similarly to if i have pointer event disabled and i hover on the image like if i go right too fast or if we have different offsets it will disable the hover so we do also have a pointer event disabled or none on our cursor just so that the hover effect doesn't go away so you can see as i'm hovering on the image that hover effect doesn't go away had i have pointer events disabled it will just hide the image because we are not hovering on the text anymore we're hovering on the image i felt like that didn't even make any sense when i explained it but deal with that uh width is going to be set to 24 rim on this the position will be set to absolute our background size is going to be set to cover our background position will be set to 50 our z index is going to be set to 99 and then we have an overflow of hidden and honestly looking at this so uh looking at this i don't think we need background size cover or background position initially when i had built this i had laid out the the image to kind of have to be a background but i think since we're using gatsby image i've since then changed it to where we have an image in our thumbnail so i honestly don't think we need to even write background size background image i think this was when i was just trying to do a background image rather than an image nested in the floating image we'll take a look at that later so this is the floating image here um let's actually take a look at if we comment this out yeah my point exactly i never check or clean my code before making a video uh let's move on though we actually want to hide this so we'll just give it an opacity of 0.1 so that we know it's there but we don't care about it right now let's work on the lines though this is where it gets a bit tricky but if you follow along you should be fine we're going to set the line height to one pixel and then the width will be set to 100 percent our background will be set to a color of black not bulk black oop black uh then our margin bottom is going to be 0.8 rem our position will be set to relative then we're going to have a display of flex and we're going to align items to center now i'm going to create the different uh kinds of classes that we can provide our line and then we'll see how that turns out here in a second when i when i show you so we'll use an ampersand and add flex 0. so if the line also has a flex class name of flex zero or has a class name of like zero uh what we're doing is setting flex to zero and i am using a pseudo element and after pseudo element for these circles so we have this circle this circle this circle the circle these are all after pseudo classes or pseudo-elements which means that if we want to hide or set like zero we also need to hide that after pseudo element so i'll say after and i'll say display none what i'll do next is use an ampersand of flex dash one uh this will receive a flex of one so you're kind of seeing the idea here i'll copy these two more times and i'll pass in two it'll be flex two and i'll say three this will be flex three all right perfect what we can do next is actually work on that after pseudo element um and to do that what we'll say is if we have the um i'm trying to think okay i got it now so if we have an after we'll go ahead and build this and then we'll adjust dependent on the left and the right because if we take a look here we do have on the right ones it's supposed to be on the left on the left one supposed to be right so we could adjust that but if we take a look at what we have now you can see that it is um you know both on the same page here but we'll fix that so for our after pseudoelement we'll do a content of empty parentheses set the uh position oops set the position to absolute our height will be six pixels our width will be six pixels the border radius is going to be set to a hundred percent and then for our background color we'll go ahead and give it a background color of black what i also want to do is for our right element it's going to be positioned or our left element is going to be to be positioned on the left so i will say the following so i'll say if the line has a class name of left we will say the after pseudo element will be a write of zero perfect let's go ahead and save that and we can take a look now so you can see that we do have these dots working for us perfectly the first line doesn't have a or a line on the left which means we need to set the line the left to have a flex of zero and we'll do that right now we do have a mask but we'll worry about that later let's go back in our layout js or sorry in our menu js and for our line left since this is our first one we'll pass in a flex of zero and then we'll take a look perfect so you can see that it is now hiding that left element but then we still have this dot which means we need to fix that if we scroll to the top we'll see we have a flex zero and then inside the flex zero we have an after suit element with display none okay so i realized i messed up because it's supposed to be a semicolon rather than a dot and then now it should fix one thing i'm a bit uh confused about which i think i made a mistake is why is air max 90 being wrapped versus here it isn't so let's actually take a look at that okay so after quick debugging uh the reason why this is being wrapped is because we haven't defined a flex for our right which means that we need to pass in a flex of 1 here and then this will allow us to fix that so we have flex 0 flex one if we wanted to you know change the positioning we'll say flex one on the left and flex one on the right this will center and equal out the widths on both ends if we say we want the left one to be larger we'll say flex two while also having flex one here and finally if we say zero on the right this will just push into the far right okay so it's really up to you on how you want to lay it out the final mock or the final demo that we have we have it laid out far left and then on the right is one okay so let's go ahead and adjust that we'll say a flex of zero on the left and a flux of one on the right and this will push it far right perfect so we've got that laid out what i'm going to do next is loop in the data so that we can have all of our list items and then just pass them down through our props and create our own list component so let's do that next what we can do is jump back in our project and then at the very top let's go ahead and bring in the data so we can say the following we can import we'll just say data from dot data for slash products dot json and if we scroll down to where our list starts happening so we want to take list out here we want to take this off and we want to create a different component for our list so we'll say const list um i forgot i'm completely blanking so i guess the cons list and then create a react component and just return a single list and then now in this list we'll return it back in our unordered list but then looping through our data so we'll say data.map and we'll just say list here and then we'll return the following so we'll return list and we also need to pass it a key right so i'll say key and for now we can just say an index which means that we need to return list index here so now what should happen is we're going to display a list four times because that's how many endpoints we have or data points we have um but it's going to be all the same data we'll switch out the data here in a second so let's see if we have air max air max air max air max and everything just looks the same but here's where we're going to start changing that out so back in our project we can carry on now this list parameter represents a single data point that we have in our data json we can open that up so command b let's go to data products json and we don't necessarily need index here we can just say list that id and this will turn a number or we could say you know list or sorry list id returns the path we can say anything as long as it's unique and different so you can see if we break this down a little we have the title the id we also have line left flex and right line flex and what this is uh is determining what the flex should be on each individual one we also have thumbnail position as well as offset for our um you know additional offset for our hover so you can see that we also have you know from the right we have 200 or 300 pixels from the left we have two 300 pixels 600 so it all depends so let's go back here um and then we have our source which is our image source let's go back to mini js though what we're going to pass our list is several props so the very first thing we're going to pass is the title so we'll pass title and title will equal list dot title now to use title we'll use the structuring to bring in title and then for our title here we'll just replace it with title and then boom you'll see it all gets updated air max new balance air max easy so we're going to do that for the rest of the dynamic data that we have such as the offset and the source and the id in the thumbnail position so for now we'll say source to bring in source so list dot source and source is going to replace this here so just say source now this will update all of the images to match the correct shoe and i'm actually going to hide or set the opacity of floating image to zero because i just don't want to see it right now so floating image will be set to zero and then let's go back to many.js one thing i also want to pass is the alignments of the uh you know the number regarding our flex for our lines so we'll say left line flex is equal to line dot left line flex okay and so left line flex will be then be determined here which means that we need to use template literals for uh this class name so i'm going to copy everything i have here put some brackets template literals get rid of the quotations and then for our number since we're only returning a number if we go to product json we're turning right flex is one the flex is zero three one one three uh we'll just return that so here we'll say dollar sign and then we'll pass in left line flex don't forget that you also need to bring in left line flex here we'll do the exact same thing for right line flex as well so just bring in right line flex and then in the props that we're passing down to list make sure we bring in right line flex as well whoopsie right on flex is equal to line dot right line flex and then all the way at the bottom here i'm actually going to copy what we have so i don't need to just write it again i'll replace that class name of the right class and then just update the left to the right so line right flex will be your right line flex and this will update all the lines so i did get an issue line is not defined what is line i put line dot which is it should be list dot i don't know where that came from okay so now you can see that the flex is being added to all of the following and let's check if it matches it does match perfectly we need to work on the images so the images have their own position that we also have in the data so in the product json we have thumbnail position so let's bring in thumbnail position we can say thumbnail position is equal to list dot thumbnail position and then we also need to destructure for thumbnail position and then for thumbnail position here we do have thumbnail and what we can do here is just write an inline style prop so we'll say left is set to thumbnail position and then this will sort out where we display our images you can always edit this to your liking in the data so products.json if we want the thumbnail position of the first image to be 400 you'll see that it just moves closer to air max 90 but this is all to your liking this is all preference so you can always edit that if you want um in our link we do have product forward slash a we need to change this so that it could take us directly to the path which the path does represent the id so what we could do here is we're saying i mean we could say path right yeah i'm thinking or id we'll just say id is set to list dot id and then we'll pass in id here which means that we'll then use dollar sign id for our product so now if we click new balance it will change the path to new balance off-white will change the path to off-white air max 90 easy but the menu is not going away so we can't actually tell if it's going but that's where we'll adjust that in terms of turning the menu on and off turning it on turning the menu on and off um so it won't have any animations just yet but we'll adjust that in a second so we've got the air max 90 new balance x90 we've got the titles we've got the layout set we've got the images and then we also have the thumbnail or sorry the floating image added as well so that is all taken care of in terms of the look now to toggle this on and off what we'll do is switch gears to our layout.js and inside layout.js we're going to house the state of our menu we'll do is we'll need to bring in use state and then we'll do the following so we'll say const menu state and then we'll say set menu state this will equal to use state and we'll set that to false so initially menu state will be set to false meaning it's not opened now to open and close the state we need to pass the state or the set menu state as props both to our header and both to our menu because with our menu we can close it with our header we can open the menu since there are two different screens or two different components for our menu we'll go ahead and pass set menu state as well as passing menu state all right now let's go back to menu.js and what we're going to do is we're going to wrap the entire menu sort of with a ternary operator letting us know that if menu state is true we want to display this component if menustate is false we want to unmount this component now we can access the state using destructuring so we have menu state and we also have set menu state and now what we can do is copy everything in this div here and then we'll use a react fragment and then we'll say the following oop so we'll say the following so menu state and since we don't want a ternary operator we'll just do and and and which is if it's true display this since we don't have an else you'll typically use ternary operators if you have an else so if you have like an fl statement but we don't want to display anything else we just want to unmount that completely and then we'll add parentheses and display this so now it should hide because menustate is false you can see that it does hide here if we change the layout.js menu state right here to true that will then be true and then it will display our menu we'll set it to false for now and if we go back to layout.js let's focus on opening up this menu we only need to pass set menu state as a prop for our header because we don't care about the state of the current menu if we open up header js we can then bring in the set menu state like so and what we'll do is we'll run an on click event handler on the hamburger menu which will then toggle the state so inside the hammer menu will say on click and this will set menu state to the opposite of what menu state is so since the default is false it should ultimately always be true opening up the hamburger menu if we take a look now uh you can see that we do get errors which we're infamous for and it does say an error mini state is not defined um where are we saying oh menu state here okay so i did lie to you guys we do need menu state so i wonder if it works okay that's cool it did work but we didn't pass menu state as a prop which is weird but we'll pass it anyway ultimately we can get away so now if we click on it turns true and it opens up the menu but ultimately we could also get away since we do have two different on clicks we just get away with not necessarily the opposite which this represents like a toggle right you're toggling true false true false true false here we can just say true and it will just turn it on and then if we close or click the x button it will set to false so you really have two options i will leave it as true until we adjust it and then i'll go back to the opposite but it's really up to you so one thing i want to do next is when we click on the x button i want to hide the menu this is in our menu js so what i'll do is look for that x button so we have close so also write an on click here on click will run the following set menu state to false oops false so now if i click on the hamburger menu it opens click on the x it'll close pretty simple stuff right nothing special again you could use the opposite which means that this will be the opposite and then in our header this will also be the opposite so right now it is false toggling will set the opposite true toggling again will set the opposite which is false all right if we refresh make sure everything is working everything is good it's up to you typically you want to use this opposite when you're clicking on the same button meaning if this also toggles close so a lot of sites out there what they'll do is just you know animate this hamburger menu into an x icon and then you can close but for us we are using a different x button up to you um do you do you so last one i'm going to lastly what i'm going to cover before we start jumping into all the cool stuff is when i open the menu i select new balance x90 i want the menu to hide so how do we determine the menu should hide what we're going to do is use a use effect hook which will only run when the location has changed in the route that will be located inside of our header uh and so you can actually put it anywhere but i'll put in the header what i'll do is the following so in gatsby they do in fact use reach router and then what we could do with each router is use a used location hook which will determine the current location or the current page you're on so we'll say from at reach router now to use the use location we'll just say const location is equal to use location and then we'll use our use effect so use effect and then we'll also need to bring in use effect from react i don't like when something is above my react imports makes me mad so in the use effect we don't need a cleanup our dependency is going to be location so when location changes uh we're going to run whatever is in this use effect and what this use effect is going to do is set the menu state to false meaning that it's going to close our hamburger menu so if we take a look now we are on the new balance x90 product page we click on the hamburger menu we want to switch to the air max 90 page we are suddenly switched to the air max landing page if you want to go to the uz 700 it will switch perfect so that's going to really do it for functionality-based right making this work but here's where we're going to take it from it looking like a 5.5 to an absolute 10 which you know is the animation part which is what you're all looking forward to so let's actually start that what we're doing is we're going to animate the menu right we're going to animate the menu to this effect we'll then add these panels that you see and then we'll finally top it off with adding the hover effects such as the floating image and this custom cursor that only shows when you're hovering on something so it doesn't display when you're not hovering on a link but then it only displays when you're hovering on things you can actually toggle which is pretty neat so let's actually go ahead and get started on that in the next section okay so like i mentioned we're going to start animating the hamburger menu what we'll do is we'll go ahead and animate the actual menu itself and then we'll add a panel's effect that you had seen earlier if we take a look real quick the paddles effect that i mentioned is what you see right now when it goes from the left and right up and down type of thing and then we'll create the mass position hook as well as add the custom cursor and floating image effect so let's first do the effect in terms of animating the menu what you see here when the menu start animating so let's go ahead and do that we can close the menu and open the menu but there is no cool animations so let's close it and to get started we'll start in the menu js we'll close product json we can close layout.js header.js as well as the menu sas file working uh strictly in the menu js what we're going to do first is import framework motion so we're going to import two things we're going to import motion as well as animate presence if you don't know too much about framer motion i do recommend you go watch my older or previous videos this topic gets a bit more advanced here uh so check that out if you want to learn kind of more of it uh more about you know basic framer motion stuff but i'm not going to spend too much time teaching here because we are um you know we're reaching a point where it's just a really long video so the first thing i want to do is i want to wrap the entire menu state with the anime presence or the menu itself with animate presence what this will allow us to do is add some exit animations uh for when our component of this product div unmounts so i will copy everything that's in this menu state let's go ahead and copy that and then i will add an animate presence and inside animate presence as its child i will then add this product stiff if i save this and take a look at what happens you'll see that if we click on the menu it does open and if we exit on it it does not close the menu that's because we haven't defined an exit animation to create a very subtle exit animation i will wrap the parent which is a product with a motion.div which will turn this product into a motion component and then i will pass it and exit prop this exit prop is just going to set the opacity to 0. if we take a look now if we open up our menu it will open up and if i click x it will then fade it out so you can see it has a very subtle opacity or fade out effect which is very very easy to create but it isn't all that appealing to us i'll go ahead and leave this exit as an opacity of zero just so that we can get rid of the hamburger menu what we'll do next is give this ul unordered list a motion oops a motion dot ul which will turn into a motion component the props we're passing here are as following so we'll pass variance and now variance allows us to extract the animations into its own variables um and then we can kind of define different states for them we're going to keep the same states that favorite motion provides which is initial which means the initial state of your animation animate which represents the current motion or animation and then exit which defines when you're unmounting the animation so i'll leave variance as empty for now until we build it and then we're going to pass initial and we'll say initial will equal initial if i just know how to spell initial animate will be set to animate and then exits will be set to exit we aren't really using exit props here for our animations except for the panels so if you see that if we click on the exit nothing happens to our menu itself it stays the same but it just goes away once the panels have reached that middle point of covering the entire screen let's go back uh because we do have an error and the error is regarding our variance so the variant we're going to make is we want um to create a staggering effect for our children which means that when we click on the menu we want each animation to run one after the other and not all at the same time i'll get to the variance part in a second in terms of adding staggering but for now we'll just leave it as commented and then we'll jump down to our list component and then we'll start animating here we'll turn this li into a motion component the very first animation we'll do is for our titles so if we look for our h2 we can find it right here we're going to animate the text itself so we'll say this div right here is going to be a motion.div and then for this animation what we're going to do is just have it slide up so we'll give it a variance and we'll call this title slide up now to define variance what we could do is scroll to the very top and then create a section dedicated to our variants also want to make a static or a default transition and so this transition is going to have a custom duration as well as an ease so we'll say transition and we'll call this const transition is equal to the following so as a default we'll say the duration will always be 0.8 and then we'll set the ease to the following so you can add custom easings in framer motion which is really neat the custom easing we are adding is a 0.6 a negative 0.5 a point zero one and a 0.9 and we'll reuse this transition across all of our animations or most of our animations so like i mentioned the first variant we'll create is for the title so we'll call this const title slide up and now const title side up or title slide up is going to have an initial set to a y of 200 pixels which means it will push it down 200 pixels and then our animate will be set to a y of 0 which is its default position we can take title slide up go all the way down and pass it here we're already passing it here so let's take a look at what happens when we open up the menu so you can see all the text just kind of flies in now i'm not the biggest fan of framework motion's default easing so what you could do is pass transition and then just pass transition here like so now when we open up the menu you can see it's a lot smoother for how the text appears like i mentioned before in terms of the staggering effect we need to add that to the parent of our list items which means it will be our ul we'll uncomment this variant and then we'll pass parent here for this variant so we'll go all the way to the top and we'll create a const parent and all we need to define for our parent is our animate prop we'll say transition is set to a stagger children of 0.1 and then we want to delay the children from animating uh for one second so they won't start animating until a second has passed from when we've opened up our menu so if we go back to our project now we'll click on it and then one second later it will all fade up and in perfect and you can see it does have a delay so it'll go one two three four we can increase delay if we want let's set it to 0.6 but this or not the delay but we can increase the stagger which will take point seconds off of each individual one from animating we don't want that we kind of want it a bit smoother 0.1 is our perfect number so if we scroll down uh we'll start animating the lines so we can get these lines working and then we'll work on the images as well now if we go to our lines real quick you can see that we do have a mask which i never really talked about or i did mention but we haven't started on them so what i'm going to do is uncomment these masks and then we'll jump into our menu sas real quick so let's save that uncomment the mask save that and then go to menu sas and if we look for our line we can then add that mask class or create the mask class we can set the background here to a background color of pink and we're using pink just for demonstration purposes we're going to make them white but we want to see how they look right we want to make sure that they're actually covering our lines we'll set the width to a hundred percent we'll set the height to six pixels we'll set the z index to nine and then we'll give them a position of absolute let's save that and take a look if we open up the menu you can see that we are covering the lines but only on the left ones if we go ahead and add a right class so if our mask also has a right class we'll set the right to zero which will then move uh the ones to the right it didn't do that um and i wonder if we jump into minijs and look yeah so right here it didn't we didn't comment out this mask for our right so make sure we comment that out and we already have a right class on our right mask which now if we open up the menu should cover all of them up perfect now we want to change this back to a background color of white what do i have yeah white um and then we'll animate the menu or we'll animate the masks to change the widths so to do that we'll jump back into menu js we'll start with the left first and then we'll worry about the right after so with the left if we select this div mask we'll turn this to a motion component i can't get that thing right um motion.div and then for our variance we'll pass this a what should we call this we'll just say mask any or mask animation um we'll also give the mask animation to the motion or the right one after we complete this though let's create this mask animation let's scroll to the top and then we'll say const mask animation is set to the following so initial this will be set to a width of 100 and then our animate is going to get a width set to zero okay let's go ahead and save that and there's an error i need to make sure i add comments from when i'm using percentages so make sure not a comment sorry but a parenthesis make sure you add parentheses so we'll save that and then if we take a look now and click on the menu you can see that it did reveal it but it was a bit off in the easing and the duration and we'll fix that here in a second so what we could do is scroll back down to the mask animation and then we'll pass a transition and for this transition what we're going to do is the following now we want to use the default transition that we have defined up at the top here but we want to increase the duration and we can do that by just using that spread operator we'll do dot dot oops dot dot oh my god dot dot dot transition this will bring in the values or the properties of transition that we defined but we can edit it or add to it by adding iteration of one now if we take a look perfect so the lefts are all animating let's do the exact same thing that we did for our right we'll scroll down we'll turn this mask right to a motion component and then we'll pass the exact same props that we did for the left so we'll pass variance mask animation and the transition let's go back in our project open up the menu and you can see that is animating perfectly now one thing that i will actually we'll get to the hover effects later but now let's work on the thumbnails so let's look for the thumbnail which is right here and now the thumbnail is going to be pretty much the exact same thing that we did for the lines we're going to turn this mask to those the variants in the transition but we need to actually style this mask so let's look for thumbnail right here we do have this masked glass but we haven't styled it let's style it to where we create a white box that covers the image so again we'll give it a background color of pink just so that we know that it's covering completely we'll give a width of 100 percent a height of 100 percent a position of absolute and a top of zero let's go back in our project and now you can see that pink box is covering all of our images we'll turn this to a background of white and then we will add that animation of that uh mask animation that we created earlier so honestly i'm going to copy and paste what we have make sure you turn this mask to a motion dot div and then pass in the variants for mask animation as well as that custom transition let's go back in our project and when we click on the hamburger menu you can see that it's all animating uh perfectly now awesome let's do it one more time perfect uh what i want to focus on next is creating those panels um the ones you see here so if we close you can see the panels come up reveal the page panels come up reveal the menu so let's actually work on that next let's go back in our original project here let's make sure that it's working in terms of the links too so if we select easy it'll just fade into this page cool okay let's do the panels uh panels is going to be its own separate components so we'll do const panels and we will return the following now this gets a bit tricky um but the way this is built is honestly pretty pretty cool for our panels we'll use a react fragment and then inside the react fragment we'll create a div with the class name of left dash panel dash background and we will copy and paste and switch this to right panel background let's go ahead and grab this panel's component and we're going to want to render this panel's component in our menu so the panel's component will live as a sibling to the products which means that we can just drop it right here oops drop it right here but we're going to get an error because in react you cannot have siblings for when you return that component so we're going to need to use a react fragment here and then drop that and looking at this i don't think we need a react fragment above the animate presence since we're using it here so now we are returning the panels but they don't display anything because we haven't animated them just yet so let's actually work on that if we go to menu sas scroll all the way to the bottom let's actually work on the panels we'll say dot left dash panel dash background we'll set the height to 100 viewport height and we'll set the width to 50 viewport height or viewport width actually we'll give both of them a position of absolute as well as a z index of 11 and then i will want the exact same thing for my right dash panel background um the only thing that's different is on the right panel background it's going to be [Music] a write of zero so let's make sure we add that go ahead and click that like so um and then if we view nothing happens uh what we need to do is actually set a background color to pink and nothing actually happens and i wonder why we can't see the panels let's check out the elements so we've got our main do we need to open the menu okay yeah that's why so it isn't actually mounted it's only mounted when the menu is clicked uh so we have our panel we can do right panel of the background of light blue not lightness light blue so the right is light blue pink perfect we aren't going to specify the background color here we'll specify it when we use turn these into a motion component so here is the trick on how this works what we'll do is work on the left panel first actually let's leave a background color because the background color is different so you'll notice when we open the hamburger menu this color is a bit purplish and when we close it the color is greenish they aren't separate divs in terms of open and close they are the exact same it's just we have state that determines if we're opening or closing and it results in changing the color of the background of the panels for now we'll leave it as a blue and pink just so that we can see what's going on let's go ahead and turn the left one to a motion div and let's create that animation our initial will be set to a height of zero then our animate is going to be set to the following so what we'll do is we'll set height to an array and then we'll say zero and then pass it window dot inner height and then we'll set it back to zero now let me explain what this is real quick because i don't think we've seen this before in the past this is a way to use key frames in frame of motion so what we'll do is what we want the um what is it called what we want this to look like is we have if i open it we have the height goes up to a hundred percent and then the height goes back down to zero if we close again you can see height 100 and then back down to zero um and so when we reach 100 that reaches the middleway or halfway point of our animation and then when we start animating to set the height back to zero that's when we change the height of the of the panel back to zero towards the end of the animation so again right here we're starting at zero once we reach the halfway point which is point five of our animation it's going to set the height to a hundred percent or the the height of our inner height and then we'll set it back to zero okay so we also want to change the bottom and now what bottom is um is where it was positioned in terms of it being positioned absolute whether it's top bottom left right the animation for our left panel you can see it's starting at the top oops not that one it's starting at the top and then going to bottom so what this means is if we have bottom here what we're going to do is first set the bottom to null and then once we reach that middle way point we want to change the bottom to have a zero and then we can just set zero at the end so let's actually take a look at what it looks like now when i open up the products you'll notice what it did for the left one it's really quick and that's because the transition isn't added so let me add custom transitions i'm going to copy what we did for the line right and i'll pass it in for our left i will only change the duration to a duration of two and then we also need to pass in times and it tells us what the definition of times is so when animated keyframes times can be used to determine where in animation each keyframe is reached each value in times is a value between zero and one representing the duration so this is kind of specifying um where kind of like our timestamps should be so we'll start at 0 once we have 0.5 that's our middle way point and then one is our ending so we'll take a look here right the way framer motion kind of defines keyframes and a lot of you know it's motion values is through ranges uh using these arrays so we have the beginning which is zero so initially we're at zero uh you could see our height is at 0 as well once we reach that halfway point of our animation which is 0.5 we'll set the height to 100 or window inner height and then our final once we've reached the end of our animation which is one second will reach back down to zero so if we take a look now and open up our menu look at the pink panel it will go up height 100 to reach that halfway point and then set the height back down to zero now this bottom part let me delete this to show you what happens if we don't define the bottom what's going to happen is that the panel should just reach 100 and then go back to zero so you'll see here which is 100 and then go back to the zero from the top that's why we're adding that bottom so once we reach that halfway point we set the bottom to zero making this position absolute element set back to zero it's kind of like defining the origin you can switch the origin from top bottom left right but since we're using position absolute elements we'll use the bottom zero which will reveal it like so okay perfect next we need to look at how our exit animation is going to work for our left panel so if we look here i can't actually close this let me comment out the right panel background so if i open it it animates like so and then if i close it it's just going to fade out but what i want it to do is this right here if you look at our final project it will go back to the top so it starts at the top going bottom and then when we close it goes from bottom to top all right so to do that what we'll do is we'll take exactly what we have for animate copy and paste it we'll switch animate to exit and then for our exit what we're going to have is the height set to zero window enter height zero nothing changes there but then we'll change this bottom set it back to top so now we set the top back to zero once we reach that middle point so let's check it out let's see if it works we'll open up the menu pink panel goes and now when i close pink panel should go up which it does perfect now it did fade out that's because we have the exit opacity of 0 here on our motion here but i think i think what we can do actually is i mean even if we add like exit exits right there shouldn't be an animation so it animates in closing animates out and then it will close it will only close once the animation is complete uh right here uh that's not how we're going to do it though what we're going to do is um you know um i'll talk about it later we'll talk about that exit animation later but let's continue on let's do the exact same thing what we have for the left panel for our right panel i'll copy and paste because i don't want to write all everything all over again i'll take the right panel background class name and i'll paste it in far right we can get rid of those comments now things that are changing though is the following we're leaving transition the same we're leaving initial the same the animate is going to be a height of zero window inner height zero similar to oe head and exactly the same for our exits the main thing that's changing is we're switching the bottom so for our animate is going to be bottom which is going to be set to zero because we want it to start off at that zero position and then once we reach the end we want to switch this to window dot inner height and then for our exits we'll switch this to bottom like so so the only thing that was switched was our exit was going to receive a bottom rather than the top and then for our bottom it was going to be 0 0 window inner height rather than null 0 0. save that and let's take a look now we open it up both panels do what they're told and then they're brought back down perfect so that is one reason why i described or we'll take a look at you know that exit animation here in a second is because when we close this we want it to exit now we don't want to see the menu once the panels are gone what we have here is when we click it uh we have this open and then when we close boom the menu is gone we see the page back to normal so let's let's work on that so we've got the panels working which is perfect before we jump to the next section what we're going to do is create that um that background color change for the exits this means we can get rid of the background pink in the background light blue in our styles get rid of that uh what we'll do is we need to somehow determine um some sort of state to let us know when a panel is completed um so first we'll we'll go ahead and create a state so we'll do const and we'll say panel complete and then we'll say set panel complete and we'll say use state and set that to false now we only need one of these divs to do this but there is a prop that we could pass which calls a callback function letting us know when an animation has completed and this is called onanimationcomplete which is a i mean it passes a prop but it's a method which allows us to run a function oops allows us to run a function here and the function we're going to run is just updating the state to the opposite of what the current state is so we'll just say set panel complete is the opposite of panel complete like so now what this means is we can change the background color of these different uh panels so we'll use a style prop and then we'll say the background here is going to be to determine based on if the panel has completed or not so we'll say the first color is e7 e7 de and then the l statement will have a different color and this color is going to be e7 d e7 and we'll copy this exactly and paste it in the left panel background go ahead and save that and i don't know why that cave's coming up so once you've saved it let's take a look now we've got an issue use state is not defined and that's because we need to scroll to the top of the menu js and import oops you state from the top let's go back down and we've refreshed the page or it should refresh on your own but now when we open we'll get that purple and then when we close we'll get the green we can open again get the purple we can close again and get the green perfect uh now let's focus our efforts on making the background not so jumpy so you can see that is jumping let's make it smooth to do that we'll scroll all the way to the top and then we'll work on this exit prop so what i'm going to do here is the following so let's make some room for us initial is going to be set to a visibility of hidden this isn't going to be an animation it's more of just hiding the element and then the animate will be set to the following visibility will be set to visible but then it will have a delay of one second so the transition will be set to a delay of one second i'm going to copy exactly what i have for animate and paste it and then switch it over to exit now exit is just going to be set to hidden so what's going to happen here is when we click on the menu since we know that the menu panels take about two seconds to complete we're going to get that halfway mark so the duration is two seconds the halfway mark is one second so we're giving this menu one second of delay period before it has to hide so if we click this now you can see that it is way way smoother than what we had before and it's pretty much seamless so the one second mark which is right here i'll call it click it boom one second it hides or it shows the menu in this case and then boom one second and it opens so it's that halfway mark um not very complicated to do very very easy to understand as well so i actually think that's it in terms of the animation we can then transition over to creating the hover effect comparing the two i mean they seem exactly the same i don't think i missed anything regarding the animation if we click on new balance it'll go to new balance let's start working on the hover effect of our image and then we can also work on the hover effect of the cursor let's go back home now the hover effects we are using a custom hook so let's go ahead and build that hook i'll create a new folder in the source and i'll call this hooks and inside the hooks folder i'll create a new file called use mouse position dot js and this is going to be a custom hook returning the x and the y of the current mouse position we're going to import use state and use effect from react and then we're going to say export default function use mouse position we're going to say let mouse position and then we're set mouse position equal to use state and we'll say x is set to null and the y is also set to null and then we're going to have a use effect and this use effect hook is going to run a function that will update the state of the you know mouse position so let's go ahead and do that we'll have a function and we'll call this handle position and we'll return an event and then we'll say set mouse position and this will return the following it'll be e dot page x for our x and then e dot page y for our y actually would be y okay now the way this function is going to run is based on the mouse move event handler so event listener i said handler right it should be a listener so window.add event listener is going to be mousemove handleposition which will run that function and then we'll have a return which kind of represents our cleanout function we'll say i don't feel like writing anymore i'm just gonna copy and paste we'll say window dot remove event listener rather than add uh mouse move handle position at the end we're returning the mouse position okay perfect so this is going to return the x and the y value so we can use this hook to access x and y and then we're going to call this hook in one spot you can typically call hooks in multiple spots but since the way our site is laid out we can call it in the layout and then pass it as props to wherever it is needed if we jump to um i'm just blanking right now components layout.js we can call this hook at the top i'm going to import use mouse position and we're importing this from the hooks folder specifically use mouse position now to use the user mouse position hook all i need to do is create const and then i can use the structuring to grab x and y and then it's set to use mouse position now i can pass x and y down as props to anywhere i want it and then just use x and y rather than needing to call this mouse position hook in different areas i'll go ahead and save this and one thing i also want to do is i want to lock the body or prevent the body from scrolling when i have opened up the menu so i'm getting an error i wonder where this area is input is not defined that i leave input here yeah input is a dependency so it's not going to be input frankly it's just going to be an empty array so go ahead and delete the input save that close use mouse position um let's take a look perfect so now it's working but one thing i was talking about is i want to stop the menu from or prevent the menu from scrolling and it doesn't show here but if we click on for example air max 97x off white i need something with long content body no that's fine actually we don't even need to do that don't you worry about that it was just going to set like a lock or overflow hidden on the body so that you can't scroll when this is when the menu is opened but to do that all you need to do is just you know have a use effect that will just set the class name of body whenever the menu state is opened which is very very easy to do but we don't need it here so for us to work with these x and y's what i'm going to do is pass them as props to our menu so x here y y and then in the menu we can just use the structuring to bring these in x and y and since we also have children or the list as a child this means that we're going to need to pass x y here again so it's kind of like three level nesting x x y y like so and then we can finally use x and y within this list all right perfect so if we look forward to or if we look for the floating image what we'll need to do here is set this as a motion component yikes motion.div and let's create some room for us to work what i'm going to do for the floating image is set the initial to an opacity of zero and we've already done that earlier here in the css but let's go ahead and get rid of that actually so floating image we can get rid of this stuff we can get rid of this opacity we'll just comment it out for now if we look at our project open up the menu okay so the initial is set to opacity of zero which is what we want let's go back here and then let's create some more room for us to work we'll set and animate to the following so we'll set the opacity to one and this is going to change depending on if we've hovered on our title which means we need to create new state called hover state to trigger if we have hovered on the title or not which we'll do here in a second but i'm going to set the x to x and then set the y to y perfect so before we actually take a look let's work on this opacity we talked about hover state right what i'm going to do in our list is create a new state called hover state so const hover state and we'll set our state and we'll say use state and we'll say hover state is set to false but then when we animate or when we hover on this we'll say opacity is determined by the hover state if it's not however we're setting the opacity to zero let's take a look now if we open up the menu this opens up if we hover on air max 90 it should display the floating image but it's not and let's try to figure out why why that is so let's go back to our project real quick if we get rid of this initial opacity zero let's see what's happening okay let's open up the inspect elements and let's look for one of the floating images which is right here opacity is set to zero which we don't want it set to zero okay i understand what's going on uh so the reason it's not working is because hover state is already set to zero because it hasn't it's not true and the only way for however state to be true is if we hover on the title which means in the title here we will grab the parent div right here so in the title uh what it's going to do is the following so on hover start and we actually need to turn this title class name to a motion component so motion dot div so on hover start it is going to set the set hover state to true and then what we can also do is just copy and paste this again and then we can say on hover end and set the state to false so now let's take a look if we open up the menu and hover on air max 90 it hovers and it shows the the following images perfect now it is positioned oddly and the reason it is position oddly is because this is referring to the parent which means the parents of this is the menu which means if i set the top left it's only going to reach here and it's not going to be a 100 precise to where the mouse lives this only works if the component or this product image is a parent itself outside of the scope with of this menu so this menu is reaching the limits which means if i add 600 it's going to be pushed down further to the bottom right or bottom left or wherever we position it to make up for this though what i did add was a new state that can kind of you know push it to the right and align it correctly which means if we do the following what we'll do is we'll create a ref um we'll scroll to the top and we'll use a use ref and then we are going to for our li use ref and call this list so i need to get i need to do some math here i need to get where this element or each element is positioned and then subtract it from the top and the left of whatever these numbers are and we'll use that by the get bounding element or get bounding rect which will determine the top and the left and then we'll subtract it so that we can fix the positioning here so to do that what we're going to do is create new state so const and we'll just call this list position and then we'll say set list position now this is going to be used and the following so top will be set to zero left will be set to zero and then we'll have a use effect that will run the following so this use effect is going to set less position list position to the following so top will be list dot current which means which we're referring to this li element dot get bounding client rect dot top and we'll copy and paste this one more time except we'll switch top to left and this is going to generate based on the hover state so when we've hovered we're going to update the current state because we only want to show where um pretty much or the element that's being hovered on so we don't want this to always run every single time only when we've hovered okay perfect so this means that when we scroll back down to this x here we need to do some math so we're going to do x minus state dot left for x and y minus state dot top now if we save this and take a look at what happened uh use effect is not defined pretty we need to import use effect as well as the fact that i had forgotten to use ref i assigned the ref but i just didn't create it to create the ref we'll say const or let uh list equal use ref like so oops yes like so uh state is not defined what's going on oh sorry i am being sloppy right now so it's not y or it's not x and y minus state dot that's let's position that left let's push this in that top because this is what our state is currently called so now if we open up the menu and we hover on air max you can see that now it's perfectly positioned where our mouse is but i do want to add some offset uh what offset is kind of representing too is you know that position to the right i want to move it a little to the right and or a little to the left and this is coming from directly uh it's coming directly from the data i do have this thumbnail position thumbnail position and thumbnail position which determines the offset so to do the offset it's only going to be applied to rx i'll just say plus offset now offset isn't being called anywhere and that is because we need to bring in offset through the destructuring and then in our list we need to say offset is equal to list.offset and now when we hover it's right there exactly where you want it so you can see that with the mouse there's this weird easing to the images very spring-like and we can just adjust that we can go down to our animation here and then pass transition and we can say the ease is just going to be linear and this helps it to be a bit more smoother so let me hover now it's just a lot smoother nice let's go ahead and add the following um when we hover on the title i am giving it an outline for example it goes to like an outline which is very easy to do right we just go to title in the css or the sas so right here uh what we're doing is a hover so we'll say ampersand hover and then we're going to say webkit dash text dash fill dash color will be set to white and then we'll do the exact same thing for the other so webkit dash text dash stroke dash width to one pixel and then webkit dash text dash stroke dash color is going to be set to black and this is only when we hover so let's take a look you can see that now it has that outline for when we hover um the final thing we're going to do is add that custom cursor effect let's go ahead and work on that next let's just make sure everything is looking good when we click the menu air max 90 beautiful i love this animation so let's close out a menu c or scss and then let's work on the cursor so the cursor is going to live in our layout js let's go ahead and build the cursor and then we can add the custom animations to it we'll say dot cursor and we'll leave it like so let's go ahead and work on the styles first we can open up abs ass scroll to the bottom and do a dot cursor now the cursor is going to receive a cursor pointer a height of 2.5 ram a width of 2.5 ram a position of absolute a z index set to 10 a top set to zero a background color of e7 d e d e our border radius is going to be a hundred percent and for our pointer events we're going to set that to a pointer events of none so if we take a look at our project you can see that the cursor is up here on the top left we just need to assign the x and the y so that it follows follows us around um let's go to menu js real quick or no layout.js and then for our cursor we'll turn this into a motion component so motion.diff next we'll set an animate and we'll give it an x of x and a y of y and let's also give it a transition so the transition is going to be similar to our images so it's going to be transition set to ease of linear and now motion is not defined so we need to define motion within our layout so import motion from framer dash motion okay so now we have the cursor following us around neat so we need to define duration just because it's kind of slow we'll say duration 0.2 okay so it's a little quicker now but we only want this to show only when we've hovered on an element all right so let's do that actually this means we need to define state for our cursor which means we can copy exactly our menu state except that we'll just turn this to cursor oof cursor hovered and we'll say set pressure hovered by default it's going to be false now we need to pass set cursor hovered to our different components let's work with the header first so set curves for hubbard will be set crusher hubbard let's open up our header and let's bring in set cursor hubbard and what we'll do is we want the site cursor hover to be true when we've hovered on our hamburger menu which means we'll just use the on mouse enter and all all mouse enter is going to do is set cursor hovered to true and i did something wrong here forgot to add curly brackets and then we can copy and paste this and say on mouse exit or on mouse leave and set the set cursor hovered to false back in our layout.js what we'll do is we'll grab cursor hovered and we'll do two things we'll do actually one sec so you can see the position of this mouse or the position of the circle isn't correctly centered with the mouse and that's because we need to subtract 16 so now if we take a look and the reason why we need to subtract 16 is because the height and the width is 2 rem which means 1 rem is 16 2 rem is 32 minus 16 centers it so that's where i got 16 from and we've got two ram from or it's 2.5 ram 16 32 24. yeah i don't know i think it's centered enough who cares um next we're gonna do scale so we're gonna do the scale to where if cursor harvard is true we're setting the scale to 1.2 if not we're setting the scale back to one so let's take a look so when i hover on the hamburger menu it should expand the cursor so you can see that it does expand if you can't tell we can blow this up we'll do look at that beautiful we're going to set it back to 1.2 we're going to also edit the opacity we'll set the opacity to um 0.8 and if we have a number on anything it's going to be zero so cursor does not exist unless we hover on something clickable now you don't see this to on too many sites you usually see the crusher always available but i do like this i don't know something about this i do like it a lot so that's how you do the cursor effect the only thing we need to do left is replicate that effect on anything that is clickable and to do that we can open up our menu or before we jump into our menu we need to pass the set cursor hovered into our menu open your menu go all the way to the top and then bring in set cursor hubbard and then we need to pass set cursor hubbard as a prop to our list and then make sure we bring that cursor hovered in our list and then in our what is it title we'll do title we'll copy exactly what we did for our hamburger menu so on mouse enter on mouse leave paste that in and now let's take a look if it works so click here perfect so you can see the cursor is available every time we hover on a link and it will close beautiful you can do the exact same thing um for the close button we'll pass the following on the close button so when we open this makes the animation hover hover hover and then you want to close you can close it okay i think that's it i think that's going to wrap up this entire video this was a pretty long video but if you did enjoy please leave a like don't forget to subscribe if i missed anything i don't think i did if you look at the final project they look the exact same yeah nothing missed uh but yeah if you didn't enjoy it please leave a like don't forget to subscribe have a wonderful day guys uh look out for the next episode in the next week or something uh but yeah take care have a wonderful day [Music]
Info
Channel: Wrong Akram
Views: 18,048
Rating: undefined out of 5
Keywords: website, build website, javascript, react.js, react, sass, github, code, css, jsx, design to code, design, ui, ux, awwwards, dribbble, gsap, javascript animations, responsive, gatsby, hamburger menu, framer motion
Id: qvFLjZvz5Mw
Channel Id: undefined
Length: 106min 18sec (6378 seconds)
Published: Sun Aug 02 2020
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.