So now let's go ahead and let's develop the layout for our Learn page right here. So I recommend that you while you're developing this you zoom out so you see the desktop mode because the last thing we did was we created this collapsible sidebar right So we have this header here. Well, in order to fully develop the learn page, I would ask you to zoom out or expand your screen if possible so that you can see this static fixed sidebar on the side here so that you can properly develop the rest of this application. So let's go ahead and do the following. Let's revisit our main and let's revisit our layout inside of that main.
And now we can finally remove the background red for this because we know that it is working. And let's go ahead and do the following. Let's do max width. And let me go ahead and give it a value of 1056 pixels. And let's give it MX auto.
So it's pushed to the sides once it reaches that max width and let's give it a padding top of six like this there we go so now you can see how my learn page words are not expanding after a certain break point right So you can see that the MX auto is activated once we break from that 1056 pixels. Great. Now that we have that prepared, Let's go inside of learn-page.vsx and let's create some basic classes here. So I'm going to give this a class name of flex, flex-row-reverse, gap 48 pixels and px of 6. And now inside I'm going to create a sticky wrapper.
And inside I'm just going to say my sticky sidebar here. So let's save this and let's create our reusable sticky wrapper inside of the components here. So sticky wrapper.tsx. It's gonna have some props here. So let's give it a type of children to be react react node and export cons sticky wrapper it's gonna have children like that and let's go ahead and return a div inside.
Let's prepare another div and let's render the children and let me just turn off my github copilot and to the first div let's give it a class name of hidden on mobile then on large is going to be visible let's give it a width of 368 pixels let's make it a sticky position let's give it a self-end position a z-index of 1 actually I don't think z-index of 1 exists. So I'm gonna remove this. And let's give it a bottom position of 6. And for this one, let's give it a class name of MinHeight and now let's do a calculation of 100 viewport height minus 48 pixels. Because this is going to be our little header that we're going to create later.
And let's give it a sticky position, a top six position, flex, flex-col, and gap-y for all elements inside. Now let me go ahead and add the sticky wrapper here from components, a sticky wrapper and there we go. Now inside of here we have a sticky sidebar and in here we have the space needed for our feed wrapper. So now I want to create the equivalent but for our feed. So just outside of the sticky wrapper add a feed wrapper and I'm gonna write my feed.
Well my feed is good enough. Now let's go ahead back inside of the components and create a new file feedwrapper.tsx. Inside of the feedwrapper it's going to be even simpler so give it a type of props again with a children of react react node and export const bead wrapper and let's not forget to assign the props children And let's return a div which renders the children. And then in here, I'm gonna give it a class name of flex1 relative, top zero, and padding bottom of 10, so that when we reach the end of our feed we have some space at the bottom so that we can scroll. And let's import the feed wrapper the same way we did with sticky wrapper.
Just remember that you have exports otherwise you won't be able to do that. So there we go. Feed should be visible on mobile but on desktop this is how it should look like. Great! So now I want to try something out.
I want to go inside of my feed wrapper here, sorry my page here and I'm going to create this div block and perhaps I can also make a cell closing tag. So you don't have to do this, you can if you want to try it out. So I'm going to give this a height of 200 pixels and a width of full and a bg of blue 500 like this. And let's make it even more. Let's do 500 pixels and I want to copy it as many times as possible because I want to try something out So I'm gonna go ahead here and there we go.
I should now be able to scroll. So I'm scrolling right now. You can see how I reached the end of my blue bars here, but you can see how the sticky wrapper stays in place. So that is the exact effect I wanted to happen here. Great!
So now what we can do next is we can create two components, one being the header and one being the user progress, which later are gonna be filled with actual values from the database, but the components themselves are just presentational, so they only accept the props. So technically we can already create them, so we see how that's going to look like. And then for the rest of the stuff, we are going to have to start creating some database items. Great! So of course if you have created these things you can now remove them.
I think this is even simpler for me to do. I'm just gonna add the feed wrapper again and write my feed. Great! So we ensure that the sticky wrappers actually stays sticky and the feed wrapper actually holds our feed. And now that I think of it you might not even need flex row reverse Instead you could remove this and then you could add this in this position.
So feed wrapper first and then the sticky wrapper. I think this should still work as expected. I think I might have just been experimenting in my original source code when I added this or perhaps I wanted it to be prepared for a mobile view where the sticky wrapper is gonna be on top something like that but for now I'm gonna stay true to my source code so I'm gonna write flex row reverse just because I don't want any additional issues to be caused but I am pretty sure that I was just experimenting with something and we actually might not need that but then again I don't wanna cause any problems later in the future. So I recommend you do the same. Leave the flex row reverse, put the sticky wrapper in the first position, and then the feed wrapper in the second position.
If you want to, you can add a little to do comment to try and remove that later and reverse their positions to see if everything later works as intended. Great. Now I want to go ahead and I want to create a very simple component here called a header. So that's going to be inside of the feed wrapper here. So I'm going to write header like this and I already know that the prop it's going to accept is going to be, for example, Spanish.
Basically, it's going to be the name of the course that the user is taking. So now Let's create this header component, but this is not going to be reusable. So it's only going to be inside of this learn here. So I'm going to go ahead and create a new file, header.vsx. And since this is a component, I can do export const header.
I don't have to do export default here. And let's just return a div for now. And let me just already prepare the props here. Title, string, and let's go ahead and add, let's destructure this. So props, the title, let's save it.
And let's import the header from .slashheader, so don't accidentally import it from our marketing folder, right? That's the landing page. Great, And now let's actually go ahead and style this. So I'm gonna give this a class name of StickyTop0BackgroundColorOfWhitePaddingBottomOf3. On large, we're gonna give it a padding top of 28 pixels.
Blacks, items center, justify, center. My apologies, let's give it justify between. Border, bottom 2, margin bottom of 5. Text neutral, 400. And on large, give it a z-index of 50.
Because on large we are gonna have some other floating elements which are possible to overlap with our header. So we want to ensure that the header has a higher index. Now let's add our link from next slash link. So just make sure you add that import. And let's add our button from add components UI button.
I'm going to give this link an href of slash courses which we are going to create later and inside of the button I'm going to use the arrow left icon from Lucid React so make sure you have this three imports here So link arrow left and button and let's give the arrow left a class name of height 5 width 5 stroke 2 and text neutral 400. Let's give the button a variant of ghost and a size of small. And outside of the link let's add an h1 element which is very simply going to render our title here. And let's give it a class name of FontBold and TextLarge. And there we go.
We now have our header but there is an issue. Our text here is all the way in the right corner but I want it to be centered. Now here's a trick that we can do. Since we are using justify-between we know that it's going to align all elements equally spaced out but we only have two elements inside. We have this link and we have this h1 element.
So what we can do is we can add a little trick. We can give it an empty div and now it becomes perfectly centered. Great. So now we have our header here ready and once we go back it's a 404 because we don't have this page yet but we are going to have it in the future. And now I think we can also do the initial items for the sticky sidebar here at the top just so it aligns with our header.
So let's go ahead inside of our page.tsx and let's go ahead and create a component called UserProgress. So I'm going to write UserProgress here. I'm going to pass the active force to just be an empty object for now. I'm going to pass in hearts to be 5, points to be 100, and has active subscription is gonna be false for now. Great, so now we have to go ahead and create the user progress.
Now, user progress is gonna be reusable, So let's go inside of the components and let's create UserProgress.dsx And I'm gonna go ahead and export const UserProgress here. And return a div UserProgress. Let's go ahead and quickly add the types here. So type props in here. We're gonna have an active course which for now is gonna be a type of any but I am going to add it to do replace with database types later when we actually have some database types because we don't have them at the moment we're going to have hearts which is a type of number and we're going to have points which are number as well and has active subscription is gonna be a boolean and let me go ahead and just assign the props here.
There we go. Now let's go back here and import the user progress from add slash components user progress. Now that we've added this import, let me just change the user, the user progress active course here. So I'm gonna pretend like I've loaded an active course, which has the title of Spanish and an image source of slash es.svg. So just make sure you're using something that you have in your public folder, right?
So I have es.svg which is iteration of a Spanish flag. So if you have that you can use that. We've added those while developing our marketing page if you remember. So just do something like this so we pretend like we loaded a course. And now we can go ahead inside of the user progress here And let's give this div a class name of flex items center, justify between, gap x2 and width full.
Now I'm gonna go ahead and just remove this. I'm gonna add a link component from next slash link so just make sure you've added this import and I'm gonna give it a href to go to slash courses again and inside I'm gonna render a button from dot slash ui button but I'm gonna replace it to go to components UI button. And I'm gonna go ahead and render an image component inside. So just make sure you've added an import for next image. And let's give this image a source of active course dot image source.
And let's go ahead and give it a alt of ActiveCourse.title and let me just destructure the ActiveCourse from here And let's go ahead and be more strict with this. Image source is string and title is string. Just so we don't make a mistake while passing this, even though we're gonna replace this later make sure that you have no errors with passing the title and the image source and this type so you know that you're getting this correctly and now let's give it a class name of rounded md and border and let's give it a width of 32 and let's give it a height of 32 as well. So now when I expand, there we go. We have a Spanish flag inside of here.
And now I just want to give this button a variant of Ghost. Like that. Great. And now we're gonna do quite a similar thing, so I'm gonna add a new link button here. This one is gonna go to the slash shop and again we're gonna have a button with the variant of ghost and let's give it a class name of text orange 500 and let's add an image here with a source of slash points dot SVG which we don't have yet Let's give it the height of 28, a width of 28.
Let's give it an alt of points and a class name of margin right two. And then I'm going to render our points. And we have to destructure the points and the hearts. And also has active subscription. So let me collapse this so that you can see them.
There we go. So active course, points, hearts and has active subscription. And let's copy this link which has our points and it's still gonna go to slash shop but this one is gonna have a text rows 500. It's gonna use the heart SVG. It's gonna have 22 width and height.
The alt is going to be hearts. And we're going to have, we're going to render, depending on if we have an active subscription, we're gonna render the infinity icon from Lucid React. Make sure you import it as infinity icon. So with Lucid icons, you can either import infinity or infinity icon, right? But infinity is reserved in JavaScript, right?
So it might cause some errors. So I recommend that you do infinity icon here. So we're going to use infinity icon, or we're going to render the number of hearts that the user has. And let's give this a class name of height 4 width 4 and a stroke of 3. And let me just collapse this so that you can see.
So this is what it's supposed to look like. Infinity icon with the class name h4 with 4 and a stroke of 3. Now if I expand we have some issues because we don't have these images. So let's head inside of my GitHub repository and add those images. So inside of my public folder here, you should find points and heart.
So let me find my points here. Points, there we go. Let's download that and we should have a heart.svg There we go, so download that. All of these icons are either MIT licensed or open source. So let's go ahead inside of the public folder here.
Let's pass in the heart and let's pass in the points. There we go. So we should have those two inside of your public folder. Just confirm that. So public folder, you should have a new heart icon and you should have the points icon so now if I go ahead and refresh there we go we have the heart and we have the points perfect So you've successfully created the initial header here and some header for the sticky wrapper.
So we're gonna add some future content here in the sticky wrapper and we're gonna add some units and some lessons here in the feed wrapper. One thing that I'm noticing is that my header has this too much padding as opposed to this side here. So let me quickly revisit my header component. So it's located inside of my main learn header here. So I've added large padding top 28.
But since I'm trying to do a sticky effect on this, I also need to add large margin top minus 28 pixels. Like this. So let me try that out. There we go. So now they are nicely aligned next to each other.
So if you're wondering why I want that effect you can try that out again. Go inside of the feed wrapper here and let me just create like a little div here with the class name space Y4. And I'm gonna create like a self-closing div just to demonstrate that again. So class name, it's going to have height of, let's give it 700 pixels, BG blue 500 and full width. There I go.
And I'm just going to copy as many times as I can to create a scroll effect. So now you can see how this Spanish doesn't get moved even for a second. So it stays sticky the same way our sidebar here stays sticky. So they have the same effect. So you need to do that sticky position and that little trick with the margin top and the padding top to achieve this effect.
At least in my experience that was what I needed to do. Great so now I can just simply remove this entire div. There we go! Great! So I think this is a great start.
We have a nice little layout here and what we have to do next is we actually have to create our database and start adding some items because there isn't much we can do anymore which is static. Everything else is actually gonna have some real values. Great, great job!