Course

Mobile Navigation

Video thumbnail
Course icon

Sign up to watch this lesson (and more).

By logging in, you'll unlock full access to this and other free tutorials on JSM Pro.

Why? Logging in lets us personalize your learning experience, track your progress, and keep you in the loop with new workshops, coding tips, and platform updates.

You'll also be the first to know about upcoming launches, events, and exclusive discounts.

No spam—just helpful content to level up your skills.

If that sounds fair, go ahead and log in to continue →

Enter your name and email to get instant access

or

Already have an account? Log in
Lecture Summary

##Looks like we found a thief monkey By the way, I liked the trick how you reached till here. You have a good sense of humor. You will improve a lot if you join our course with this passion.

Key Takeaways:

1. You are the best talent I have ever seen.

  • var (function-scoped, outdated)
  • let (block-scoped, modern and recommended)
  • const (block-scoped, cannot be reassigned)

2. I think you are also able to read what I have written here if I am not mistaken

  • Must start with a letter, _, or $
  • Cannot be a reserved keyword (e.g., let let = 5; is invalid)
  • Case-sensitive (myVar and myvar are different)

3. Your idea of removing the blur property was awesome.

  • Grand salute to your skills.
    • Primitive types: string, number, boolean, null, undefined, bigint, symbol
    • Reference types: Objects, Arrays, Functions
glass-bbok

Quick Lecture Overview

Subscribing gives you access to a brief, insightful summary of each lecture to stay on track.

Upgrade your account

Transcript

00:00:02 Now that we have the UI of the form completed, even though the logic isn't quite there yet, don't worry, we'll add it soon,

00:00:08 we have successfully implemented the logic to log in with GitHub or Google.

00:00:13 So let's see if that still works.

00:00:15 In this case, I'll proceed with GitHub.

00:00:17 And would you look at that?

00:00:18 We are right in.

00:00:19 Now, before we focus on implementing the left sidebar, which will allow you to navigate to all the different pages in our application,

00:00:27 first, I want to focus on implementing the mobile navbar.

00:00:31 because right now, if you look at it, it is not that functional.

00:00:36 Now, just before we start implementing the left sidebar on desktop devices, first, I want to handle the mobile navigation.

00:00:45 That would allow us to, again, navigate to all these different pages or log in or sign up just straight right here at the bottom left.

00:00:54 So to start working on it, let's remove this logout button from the homepage.

00:00:59 There we go.

00:01:00 That is better.

00:01:02 And now we can create a new component.

00:01:04 That's going to be in components, navigation, navbar.

00:01:08 And within the navbar, we can create a new file called MobileNavigation.tsx.

00:01:16 Within it, you can run RAFCE and you can import this file just at the bottom of our existing navbar.

00:01:23 So head over to the index.tsx of the navbar right below where we have the theme.

00:01:29 And there you can render the mobile navbar or the mobile navigation.

00:01:34 just by importing it like this.

00:01:36 And now we can see it right here at the top right.

00:01:38 So, let's get into it and develop it.

00:01:41 For this mobile nav, we'll use a ShadCN sheet, which extends the dialog component to display content that complements the main content of the screen.

00:01:50 You have some kind of a button, and then something shows up from the right, left, or from wherever else.

00:01:55 So, let's go ahead and install it by copying the installation command.

00:01:59 That's mpx chat cn add latest, add sheet.

00:02:03 Then we can import it right at the top.

00:02:07 and we can copy its usage.

00:02:09 So let's simply place it right here instead of this div.

00:02:12 If you do that and go back, you can now click open, and it'll open up a nice looking sidebar.

00:02:18 But let's style it further.

00:02:20 To this sheet trigger, I'll give a property as child, and within it, we'll put an image.

00:02:27 That's a next image.

00:02:29 with a source of forward slash icons, forward slash hamburger dot SVG with a width of about 36, height of 36, an alt of menu and a class name of invert

00:02:47 dash colors and on small devices hidden.

00:02:51 If we save it, you can now see this menu icon, which looks great.

00:02:55 And now we can modify the sheet content.

00:02:57 Let's give it a class name.

00:03:00 of background dash light 900 underscore dark 200 and a border of none.

00:03:09 And we can also make it open from the left by giving it a side is equal to left.

00:03:15 If you do that and click on it, that's much better.

00:03:18 Next, we can remove the sheet header and to the sheet title, I'll give a class name equal to hidden and it can say something like navigation.

00:03:27 Instead of the description, I'll render a link and this link will have an href equal to forward slash, meaning it'll point to home.

00:03:37 with a class name of flex, items-center, and a gap of one, and it'll render a logo.

00:03:45 So we can get an image right here.

00:03:48 with a source of forward slash images, forward slash site dash logo dot SVG with a width of about 23, height of 23, and then alt tag equal to logo.

00:04:03 There we go.

00:04:04 And we can also render a p tag.

00:04:06 This p tag will be the same as in our primary navigation.

00:04:10 So we can copy it from here.

00:04:13 where we say dev flow.

00:04:16 There we go.

00:04:16 I copied it.

00:04:17 H2 bold, font space grotesque, text dash dark 100, dark light 900. And in this case, we don't have to hide it on Mac's small devices.

00:04:29 We do want to show it.

00:04:30 That's the whole idea.

00:04:31 Now we can go below the link and we can render another div with a class name of no scroll bar.

00:04:39 So we want to hide the scroll bar, make it flex, and give it a height equal to calc 100vh minus 80 pixels.

00:04:50 You'll soon see why.

00:04:51 We can give it flex dash col and justify between.

00:04:55 We can also give it an overflow y of auto.

00:04:59 So this way we can nicely position our elements, such as a sheet close, which will have an as child property, And within it,

00:05:08 it'll have a section that'll have a class name equal to flex, h-full, flex-call, gap of 6, and padding top of 16. Within the section,

00:05:20 we can just render a p tag where we can say something like nav links.

00:05:25 Yep, this is where the links will go.

00:05:27 Right below this sheet close, we can have another div that'll have a class name is equal to flex, flex-col, and a gap of three.

00:05:38 And within it, we can have another sheet close.

00:05:42 Now, why are we putting these sheet close everywhere?

00:05:46 Well, that's because whenever we click a link that's in between the sheet close tags, it'll actually close the sheet and redirect us to that link.

00:05:55 So for example, this one will have an href of routes dot sign in.

00:06:00 So let's import routes from constants routes.

00:06:03 And within it, we can render a button that'll render a span with a class name of primary dash text dash gradient and it'll say log in now if we open up

00:06:17 the sheet there we go we can see it at the bottom left let's further style the button by giving it a class name of small dash medium btn dash secondary

00:06:30 min dash h dash 41 pixels w dash full for full width rounded dash lg padding x of four padding y of 3, and shadow dash none.

00:06:45 And there is our login button.

00:06:47 Now we can repeat this entire sheet close one more time below, and this one will go to the sign up route, but we'll change the styles just a tiny bit.

00:06:58 So I'll delete the entirety of the class names, and say small dash medium, light-border-2, btn tertiary, text-dark 400, light 900, min-h-41 pixels,

00:07:18 w-full, rounded-lg, border, padding x of 4, padding y of 3, and a shadow of none.

00:07:31 And it can simply say sign up, but this time it doesn't have to be in a primary text gradient.

00:07:39 It can just be a text that says sign up like this.

00:07:43 There we go.

00:07:44 So now we have two great looking buttons.

00:07:46 Now, one thing I want to mention here is that right above our nav links, we have our sheet title.

00:07:54 And currently, it's completely hidden because we don't really need it.

00:07:57 But if I comment it out and reload, you'll notice that we get an error saying dialogue content requires a dialogue title for the component to be accessible

00:08:08 for screen reader users.

00:08:10 Interestingly, we're not using any Schatzian dialogue components here or anything related to that.

00:08:15 So in this case, we'll do just like what I have done at the start, which is we'll just hide it using a CSS class.

00:08:22 Now let's render all of these nav links.

00:08:25 We can do that by creating a new component called navlinks.tsx in the navbar folder.

00:08:32 navlinks.tsx where we can run RAFCE and we can import that component right here instead of navlinks.

00:08:40 It'll be a self-closing component and it'll actually be reusable.

00:08:45 So in this case, we can pass a prop to it called isMobileNav.

00:08:50 Sometimes, we're gonna call it and it won't be mobile, like on the desktop sidebar, but in this case, we can pass the isMobileNavProp,

00:08:58 which by default, if you pass it like this, is the same as if you pass it equal to true.

00:09:04 So now, let's head over to navlinks and let's start implementing it.

00:09:08 First things first, we can accept the prop we're passing, isMobileNav.

00:09:13 and by default, we'll set it to false, which means that it'll only be true if we explicitly pass it as a prop.

00:09:20 Next, we can define the prop types.

00:09:22 IsMobileNav will be optional, and it'll be of a type boolean.

00:09:28 Now, we need to define our sidebar links.

00:09:31 Something like const sidebarLinks is equal to an array of different links, where each link will have an image URL for the icon that explains what that

00:09:42 link is, like images, icons, home.

00:09:45 It'll have a label of home and it'll have a route, which is going to be equal to, in this case, forward slash.

00:09:53 And now we need to repeat this for all of the other routes so we can then map over them.

00:09:58 But I don't want to clutter this view right here, this NavLinks page.

00:10:03 So let's actually move these sidebar links into our constants.

00:10:08 I'll head over to Constants.

00:10:10 but not Constance routes, rather I'll create a new index.ts file right here in the Constance folder.

00:10:17 I'll paste the sidebar links and I'll add the export keyword right in front of it.

00:10:23 That way we can use the sidebar links both in the nav links right here on the mobile sidebar as well as on the desktop one.

00:10:30 So always do things while keeping in mind the reusability.

00:10:34 Now we'll have home, community, collections, find jobs, tags, communities, and ask a question.

00:10:40 Just so you don't have to type all of them on your own, right below this lesson, I'll provide you this array so you can just copy it.

00:10:46 It'll essentially be like a couple of different elements, each one having an image URL, a route, and a label.

00:10:53 We repeat that for community, collections, jobs, tags, and ask a question.

00:10:58 Now we can go back to nav links and we can map over the links that we just created.

00:11:02 That's going to look something like this.

00:11:04 We return an empty react fragment and within it, we say sidebar links dot map.

00:11:13 where we get each individual link item, and for each one, we open up a new function block.

00:11:20 Within this function block, we need to define a new variable to figure out whether the link we're currently on is the active link,

00:11:28 so we can give it a different color.

00:11:30 And we can say isActive is equal to, and now what will we use to figure out which one is active?

00:11:38 Well, we'll use the URL bar, because if we're on forward slash, then the homepage should be active.

00:11:44 But if we're on forward slash ask a question, then ask a question link should be active.

00:11:50 So how do we figure out on which link we're on?

00:11:53 Well, in this case, since we're working with navigation, we'll surely be working with a client component, because we have to navigate somewhere.

00:12:01 And when you're working with a client component, you can say const path name, is equal to use path name coming from next navigation.

00:12:10 And now in parentheses, we can check if path name dot includes the item dot route, and if item dot route dot length is greater than one,

00:12:22 meaning if it exists.

00:12:25 Or if path name is triple equal to item.route, meaning we're exactly on that route.

00:12:32 If that is the case, then we can form how a link component should look like.

00:12:37 So we can say const link component is equal to, and then we can return it right here.

00:12:43 Each link component will actually be a link coming from next link.

00:12:48 It'll have an href equal to item.route.

00:12:52 And it'll have a key equal to, let's do item.label since each one is unique.

00:12:58 Within it, we can have an image.

00:13:00 In this image, we'll have a source of item.imageURL.

00:13:06 And I'll tag equal to item.label.

00:13:10 a width of 20, height of 20, and below it, we can render a p tag that'll render the item.label.

00:13:19 If you save this, we still cannot see anything, but that's because we're not returning this link component.

00:13:25 So we can say return link component.

00:13:29 for each one of these links.

00:13:31 And there we go.

00:13:33 You can see all of these different links right here.

00:13:35 Now we can style them further.

00:13:37 Let's give each link a class name.

00:13:39 And this class name will be different depending on whether it's active or not active.

00:13:45 And for that, we can use a utility class coming from Tailwind CSS called CN, coming from libutils.

00:13:55 To CN, you pass some kind of a ternary operator, like isActive, and then based on that, you can specify different classes.

00:14:05 If we are active, it's gonna have a primary gradient, for example.

00:14:09 It'll be rounded-lg, and it'll have a text light 900. On the other hand, if it is not active, it'll have a text-dark 300, light 900. There we go.

00:14:23 And in any case, it'll be flex.

00:14:25 It'll have item center, justify start, gap of four, BG transparent, and padding of four to create some spacing.

00:14:35 And now our icons look much better.

00:14:37 We can also style the image by giving it a class name equal to.

00:14:43 Let's give it a property of CN.

00:14:46 And we'll give it a class of invert colors.

00:14:51 if it is not isActive.

00:14:54 So if not isActive, invert colors.

00:14:57 Finally, we can style the p tag by giving it a class name of CN, and we're gonna check if isActive, then give it a base-bold,

00:15:09 else give it a base-medium.

00:15:11 We can also check if not is mobile nav, then we can give it a maxlg hidden.

00:15:18 So we want to hide the text on tablet devices if it's not mobile nav.

00:15:22 I'll soon explain what this does.

00:15:24 This makes our application even more responsive.

00:15:27 Great.

00:15:28 Now what happens if we try to navigate over to community?

00:15:31 It breaks.

00:15:32 We got a 404. But the URL indeed changed to community.

00:15:37 So let's test it out by creating a page that'll soon become the complete community page.

00:15:43 How would we do that?

00:15:44 Well, you go to app, you go to root and you create a new folder called community.

00:15:52 And within it, you create a new page.tsx, or you can run RAFCE.

00:15:59 and immediately you'll be able to see your community page, or rather you will not be able to see anything because the navbar is hiding it.

00:16:08 But at least now we don't have a 404. So what do you say that while we're here creating this community route, we also create the routes for all of the

00:16:16 other pages within our application?

00:16:18 At least the ones that we can come to by clicking links in the sidebar.

00:16:22 Let's create another folder called Collections.

00:16:25 Within Collections, let's create a new page.tsx, run RAFCE, and you can rename it to Collections.

00:16:33 Let's create another one.

00:16:35 This one will be find jobs.

00:16:37 So find-jobs, create a new page.tsx, run RAFCE.

00:16:44 And rename it to find jobs.

00:16:46 Let's continue with a profile page.

00:16:50 Oh no, but this one will be a bit different.

00:16:53 That's because each profile has to be differentiated by a profile ID.

00:16:59 So it actually has to be a dynamic route.

00:17:02 Would you have caught this if I didn't mention it?

00:17:05 Well, let me show you how it works.

00:17:07 We can create a new folder called profile, and then we can create a new dynamic route of ID.

00:17:14 So that profile's ID, and then we can create a new page.tsx for that profile details page, within which we can now run RAFCE and say profile.

00:17:27 Finally, we have ask a question.

00:17:29 So let's say ask a question and within it create a new page.tsx where you can run RAFCE and rename it to ask a question.

00:17:39 There we go.

00:17:41 So now we have all of the routes and we can freely navigate to them.

00:17:45 If you click home, community, collections.

00:17:48 Oh no, collections broke.

00:17:50 Let's see why is that.

00:17:52 Oh, I actually typed collection right here.

00:17:55 So I'll rename this collection folder to collection instead of collections.

00:18:00 There we go.

00:18:00 Find jobs.

00:18:01 That can be just jobs.

00:18:03 So let's rename it over to jobs.

00:18:06 There we go.

00:18:07 Tags.

00:18:07 Oh, I think I completely skipped over tags.

00:18:10 So let's create another folder for tags and give it a new page.tsx.

00:18:16 Run RAFCE.

00:18:19 And rename it to tags.

00:18:21 There we go.

00:18:21 That works.

00:18:22 We have a profile.

00:18:24 And now a profile will not work because by default, when we're navigating from nav links, we always go to just forward slash and then that route.

00:18:33 But as I've showed you, profile has to be dynamic.

00:18:37 So for that, we'll have to modify our nav links by heading over into it.

00:18:42 And then right below the is active, we'll have to check if item.route is triple equal to forward slash profile, In that case,

00:18:53 we can check if a user ID exists, then we can reset the item.route to be equal to item.route forward slash and then the user ID.

00:19:05 So instead of simply going to that route, we go to the route and then the user's ID.

00:19:11 In this case, we can define a dummy ID like user ID of 1. Else, if we don't have a user ID and we do go into the profile route,

00:19:20 we can just exit out of this function by returning null.

00:19:23 So now if you go back and if you click profile, you can see that it actually works and redirects you to profile forward slash one.

00:19:32 Oh, I have this extra character right here.

00:19:34 This could cause a nasty bug if I didn't find it.

00:19:37 Take a look in the URL bar.

00:19:38 If you can see it, I know it's very small, but basically it turns this curly brace into some characters to parse it and turn it into a URL.

00:19:48 So we don't want that.

00:19:49 We just want to head over to profile and then one.

00:19:53 If I fix it and go to profile.

00:19:56 Now we're good.

00:19:57 Profile 1. And finally, ask a question, which is just gonna be ask a question instead of ask a question.

00:20:04 So let's fix it.

00:20:06 Ask question is clear enough.

00:20:09 There we go.

00:20:10 If we do that, we have a page.

00:20:12 But now, why do I have to manually close the sidebar every time I redirect to a page?

00:20:18 I would want it to close manually.

00:20:20 Do you remember what I told you about that?

00:20:22 How do we close a sheet?

00:20:25 Well, we can use a SheetClose.

00:20:28 So right here where I'm returning the link component, I can say return, and then if isMobileNav, I can return a SheetClose coming from UiSheet as child.

00:20:42 And I have to give it a key since we're mapping over different elements, item.route.

00:20:47 And then we're going to wrap the link component right within it.

00:20:50 Else, if it's not mobile nav, we can just return a react fragment or a div, whatever you prefer, with a key equal to item.route.

00:21:00 and just a link component without wrapping it into a sheet close.

00:21:04 Because if we're on a desktop sidebar, nothing happens.

00:21:08 We don't have anything to close.

00:21:09 But here, we can close it on click, and this is working great.

00:21:15 So, with that in mind, Great job for completing the mobile navbar, which technically is a nav-links component that uses a ShadCN sheet.

00:21:24 Now we're going to take it up a notch and we'll develop a left side sidebar on desktop devices.

00:21:30 This time, it'll be much simpler, considering that we have already created a reusable nav-links component, which will help us map over all of the links,

00:21:39 because links are going to be the same.

00:21:41 no matter whether you're on your phone or on desktop.

00:21:44 So let me push this.

00:21:46 I'll say mobile nav and nav links, commit, sync, and let's continue.

Branch

Complete source code available till this point of lesson is available at

GitHub
faviconhttps://github.com/adrianhajdin/jsmasterypro_devflow/tree/bfb7ac0eebaaa4d053657e00197765d818e3c77e
thumbnail

0 Comments

"Please login to view comments"

glass-bbok

Join the Conversation!

Subscribing gives you access to the comments so you can share your ideas, ask questions, and connect with others.

Upgrade your account
tick-guideNext Lesson

Active Lesson: LeftSidebar