
No Comments Yet
Be the first to share your thoughts and start the conversation.
Be the first to share your thoughts and start the conversation.
How did you manage to remove the blur property and reach here?
Upgrading gives you access to quizzes so you can test your knowledge, track progress, and improve your skills.
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
In this lesson, we focus on creating responsive sidebar components for a React application, including both desktop and mobile layouts. The development process includes organizing components, implementing routing with React Router, and enhancing the user experience with dynamic class management.
nav-items
component for the sidebar.00:00:02 Considering that most of our pages will use the mobile or the desktop sidebar, what do you say that we focus on the layout of those sidebars first,
00:00:10 and then we can focus on the pages that'll be within it.
00:00:13 So let's start with the sidebar component.
00:00:16 I'll first create a new folder within the root of our application, and I'll call it components.
00:00:22 And then our first component will be called nav-items.
00:00:27 navitems.tsx and then there we can run RAFCE to quickly spin it up.
00:00:33 We don't need this React import so we can always delete it and we can also create a new component within the components folder called index.ts.
00:00:43 We only need to do this once because from this one file we will export all of our other components by saying export default as navitems and then from dot
00:00:58 slash nav items.
00:00:59 This allows us to very easily import all three components within one line.
00:01:03 I'll show you how we can import it very soon.
00:01:05 But for now, let's head over into the nav items component and let's implement it.
00:01:11 First things first, I'll focus on the layout.
00:01:14 So instead of a div, I'll turn it into a section and give it a class name of nav-items.
00:01:21 Within it, we of course need to have a link coming from React Router and it'll point to forward slash.
00:01:29 This will be our primary link.
00:01:32 and it can also have a class name of link-logo so right within this link we can render an image so that's an img with a source pointing to forward slash
00:01:45 assets forward slash icons forward slash logo.svg with an alt tag of logo.
00:01:53 And we can also give it a class name equal to size of 30 pixels, like this.
00:02:00 And just below it, we can render an H1 that'll say Tor Visto, which is the name of our application.
00:02:07 You can see that WebStorm doesn't recognize this word, so it might think that we misspelled it.
00:02:12 But I'll tell it, no, save this to dictionary, because we'll be using it much more often later on.
00:02:18 Okay, so now where can we see this Nav Items component?
00:02:22 Well, we can use it within our Admin Layout.
00:02:25 So head over into the Admin Layout, and right here where it says Sidebar, within this aside, here we want to render that Nav Items component.
00:02:36 but we don't want to just render it like this.
00:02:38 We want to wrap it within a Syncfusion sidebar component.
00:02:43 So I'll first render a sidebar component coming from AdSyncFusion EJ2 React Navigation.
00:02:51 I'll give it a width of about 270 pixels and a prop of enableGestures equal to false, because this will be our desktop sidebar.
00:03:01 And within it, I will then render the nav items coming from dot dot slash components like this.
00:03:08 So you can see if we didn't have that index dot ts within components, then we would have to import every single component like this in a new line.
00:03:16 Import nav items from components, nav items, import something else from somewhere else.
00:03:21 But in this case, we can just do this and now we can add additional components like comp2, comp3, all in a single line.
00:03:31 Okay, so let's also self-close these nav items.
00:03:34 And now right on top, you can see that this application was built using a free trial of Syncfusion Studio.
00:03:40 So we'll have to get a valid license key.
00:03:43 And that's completely free.
00:03:44 So soon after you register your license, that message will be completely gone.
00:03:48 If I covered this before in the video, that's great.
00:03:51 If not, don't worry.
00:03:52 Even if the message is still right there, we can continue developing everything, and then we'll remove it later on.
00:03:58 But with that said, let's actually expand our browser so we can see what's happening on desktop devices.
00:04:03 There we go.
00:04:04 Right here, we start seeing the sidebar.
00:04:08 Perfect.
00:04:08 And we can see this Tor Visto logo that basically points us to the homepage, which right now doesn't exist.
00:04:15 So with that in mind, we can continue developing the left sidebar right here, so-called the Nav Items component.
00:04:21 So right below this link, let's render a div that'll have a class name equal to container.
00:04:30 and within it we can render a nav that's an HTML5 semantic tag for the nav items within which we can map over our sidebar items which you can import over
00:04:42 from constants.
00:04:43 So say sidebaritems.map and then you get each individual item from which we can destructure the properties, such as the ID,
00:04:54 an href, an icon, and a label.
00:04:57 And then for each one of these, we can automatically display a new div, within which, for now, we can maybe display just the label.
00:05:06 So if you do that and save it, here you can see dashboard, all users, and ai-trips.
00:05:12 But hey, where are these items actually coming from?
00:05:15 Well, if you command click into sidebar items, you'll see that this is a simple array of objects that I prepared before.
00:05:21 Each one of these objects has an ID, an icon, a label, and a path that it points to.
00:05:28 Perfect.
00:05:29 So now for each one of these, instead of a div, we want to use a React router component called nav-link.
00:05:36 Of course, you want to automatically import it from React router.
00:05:41 The to path will be equal to the href or the link.
00:05:45 And we can also give it a key equal to id.
00:05:48 Now what this nav link allows you to do is to open up a dynamic block of code and then have a callback function within it.
00:05:55 And that callback function looks something like this.
00:05:57 So you have the parentheses and then an immediate return.
00:06:00 Within the parentheses, you can destructure the isActive state.
00:06:04 So this tells you whether the component is active.
00:06:07 And we can also use Tabscript here to say that isActive is of a type boolean.
00:06:13 And now within it, we can render a div within which we can render the label.
00:06:19 If we save this now, all of them are exactly the same as before, but now we can use that isActiveState to style it further.
00:06:27 For example, this div can have a class name, equal to, and now here we want to make it dynamic.
00:06:34 So we typically want to apply some styles, but we also want to change the styles depending on the isActiveState of that nav link.
00:06:42 And for that, in Tailwind, we use something known as CN, short for class names.
00:06:48 So, within our file and folder structure, create a new folder, and let's call it lib, as in library.
00:06:56 Within the lib folder, create a new file, and call it utils.ts.
00:07:04 This stands for utility functions.
00:07:06 functions that we can reuse across the application that deal with specific functionalities.
00:07:12 The CNUtil typically comes directly with Tailwind, but you can very easily get it right here from the video kit as well.
00:07:20 So just copy the entire app lib utils and then paste it over into the utils right here.
00:07:26 Here, we'll have a couple of simple functions like formatting the date, parsing the markdown to JSON so we can use it, parsing the trip data which we'll
00:07:35 use later on, and some functions that'll help us calculate the percentage later on.
00:07:39 More on that soon, the only thing we needed right now is this one, Tailwind Merge, which will take in the static and the dynamic class names.
00:07:47 You can also notice that this utils file uses djs library to manage date and time.
00:07:52 So I'll open up my terminal and I'll run npm install dayjs.
00:07:58 Also, we can keep this library within the app.
00:08:01 That way, we have everything important stored right within it.
00:08:05 There we go.
00:08:06 So now, within this class name, you can say cn and then import it automatically from the top, from libutils, and pass the styles that it'll always have,
00:08:16 such as a group and a nav-item class name.
00:08:20 But now, as the second parameter to the CN method, you can also provide an object and say when these additional class names will be activated.
00:08:30 For example, the bg-primary 100 and important text-white will only be active if the isActive state is turned on.
00:08:43 If it's not, then they won't be active.
00:08:45 We can do a similar thing for the image next to the label.
00:08:48 So I'll render a self-closing image tag that'll have a source of icon, an alt tag of label, and a class name equal to...
00:08:59 I'll make it dynamic one more time, and I'll make it a template string this time.
00:09:04 On group hover, we want to change the brightness.
00:09:09 So I'll say brightness.
00:09:11 to 0, typically size of 5, and on group-hover, we'll also want to invert the colors.
00:09:20 You know that effect when you kind of hover over it, the background then turns darker, but the icon therefore needs to turn lighter in order to be visible
00:09:30 on that darker background.
00:09:31 So we can open up a dynamic block of code and say if isActive is true, In that case, we can change the brightness to zero and invert.
00:09:41 But if it's not, we can just leave the text color to dark.
00:09:46 So text-dark 200. Perfect.
00:09:49 So now, if we check this out in action, we can see the logo on the top and you can see that the dashboard is the currently active tab.
00:09:56 But if you click on the All Users tab, it still has the same layout because remember, we implemented this page before and gave it the admin layout.
00:10:04 The trips, of course, will lead to a 404, but we can now nicely switch between those two, and as you hover over it, you can see that it actually changes
00:10:13 the background color, indicating that it'll become active.
00:10:16 So now we can switch between those two pages within our nav items.
00:10:19 Let's also add a footer to this sidebar, sharing a bit more info about the currently logged-in user.
00:10:24 For the time being, I will hard-code the user information, just so we have something to display, but later on, of course,
00:10:31 this will be coming for real from authentication.
00:10:34 So say const user is equal to, I'll give it a name of Adrian, an email of contact at jsmastery.pro, which is my email address,
00:10:46 and an image URL of a path pointing to assets, images, david.webp.
00:10:54 I found a random David developer online.
00:10:56 So now that we have this user we can head down below this nav and create a new footer.
00:11:05 This footer component will have a class name equal to nav-footer and right at the top of that footer we can display an image with a source of user?imageurl,
00:11:20 or if that doesn't exist, we can always point to that David thing.
00:11:23 So forward slash assets, forward slash images, forward slash david.webp, and we can give it an alt tag of username.
00:11:31 So that's going to be user?name or David, maybe, in case the user doesn't exist.
00:11:39 Perfect.
00:11:39 So now if you check it out, you'll see this developer right here at the bottom left, right below the image.
00:11:45 We can render an article.
00:11:46 Article is like a div, but it says that the pieces of content within it actually are related.
00:11:53 So within it, we can just display an H2 that'll render the user?name, and then below it, we can render a P tag that'll render the user?email.
00:12:06 So if you save it and check it out, you can see Adrian and contact adjsmastery.pro, which is the email.
00:12:11 For you, of course, it could be something different.
00:12:14 And finally, below this article, we need to display a button through which we'll allow the user to log out.
00:12:21 So, to this button, I'll add an onClick and I'll just do a callback function and say console.log log out.
00:12:32 Of course, later on we'll actually implement the functionality right here.
00:12:36 I'll also give this button a class name of cursor-pointer to let people know that it is clickable.
00:12:43 And then right within it, I'll display a self-closing image that'll have a source of forward slash assets, forward slash icons,
00:12:52 forward slash logout.svg with an alt tag of logout and a class name equal to size of 6. So now, if we save this and check it out,
00:13:07 you can see that we have a nice looking logout button and that concludes our left sidebar.
00:13:13 But now, what happens if we go to a mobile view?
00:13:16 we cannot really let the sidebar take that much space.
00:13:20 So that's why we're hiding it on tablet or smaller devices.
00:13:23 So now, if I actually put this to a mobile view, you'll see that this left sidebar entirely disappears, and we have this new mobile sidebar that is there instead.
00:13:35 So let's implement the mobile sidebar too.
00:13:37 I'll do that by heading over into components, and I'll create a new component called MobileSidebar.tsx.
00:13:45 I'll run RAFCE to quickly spin it up, and we can export it from our components just by changing the name of the export to MobileSidebar.
00:13:57 And then we can import it directly within the admin layout.
00:14:01 Instead of the mobile sidebar, we can just render the real mobile sidebar coming from components.
00:14:09 There we go.
00:14:10 So now if you did that, you understand that we have a mobile on mobile, we have this one on desktop, and then we show the rest of the page content.
00:14:20 Perfect.
00:14:21 So that looks something like this.
00:14:23 Nothing fancy yet, but it'll look much better very soon.
00:14:27 In this case, we can actually see both the code and the view at the same time.
00:14:32 So it's going to be even easier to implement it.
00:14:35 I'll start by giving this div a class name equal to mobile sidebar.
00:14:41 And I'll also give it a class name of wrapper, making it act as a flex wrapper.
00:14:47 Within it, I'll display a header component.
00:14:51 And within that header, we can have a link coming from React Router pointing to home, just forward slash.
00:15:00 Within the link, we can display the logo as before.
00:15:03 So I'll say image.
00:15:05 that'll have a source equal to assets icons logo.svg with an alt tag of logo a class name of size-30 pixels and there we go you can see this shortened
00:15:22 version of the logo and then right below it we can render an h1 That'll simply say Tor Visto, which is the name of the application.
00:15:30 Of course, feel free to use something else if this doesn't look good.
00:15:33 And then since this menu will open up, we actually need a button.
00:15:37 So below the link, render a button component.
00:15:41 And this button component will have an onClick that'll be a callback function that simply needs to collapse our sidebar.
00:15:50 Okay?
00:15:51 So how do we get access to this sidebar?
00:15:54 Implementing this on our own would be super difficult.
00:15:58 sidebars and mobile navbars and whatever opens and closes, even though it's seemingly super simple, it's actually a pain in the ass to implement so it
00:16:08 works properly across all devices.
00:16:10 So that's why here we'll once again use Syncfusion's sidebar component, same as we did for desktop, So I'll say const sidebar of a type sidebar component
00:16:24 coming from Syncfusion EJ2 React navigation.
00:16:27 And then what we can do is within this button, we can simply say sidebar.
00:16:34 toggle, which will actually open up that sidebar.
00:16:38 But instead of a const, for now I'll simply set it to let, because for const, since you cannot re-declare the variable, you have to declare the value immediately,
00:16:47 but here we really don't.
00:16:48 We can just set it as undefined at the start.
00:16:51 You can see that our TypeScript is complaining right here because we're using this variable before being assigned, but we'll actually make this functionality
00:16:58 work with Syncfusion's component.
00:17:00 So for now, I will simply suppress this warning with a tsignore, which I will add right above this button as a comment.
00:17:09 Perfect.
00:17:09 So we're toggling this sidebar and we'll have a regular image.
00:17:13 This is going to be a menu icon.
00:17:16 So I'll give it a source of assets, icons, menu.svg with an alt tag of menu and a class name equal to a size of seven.
00:17:29 So if I save this, you should be able to see a menu icon on the right.
00:17:33 Now, right below the header component, we can actually render this mobile sidebar.
00:17:39 So I'll render the sidebar component coming from Syncfusion, and I'll give it a width of about 270. And of course, we'll have to import it from Syncfusion,
00:17:49 but not just as a type, which is what we have done so far.
00:17:52 we'll want to import the actual sidebar component like this.
00:17:56 So if you do this, you'll see that it'll automatically be opened and it'll hide our logo.
00:18:02 So we'll need to give it a ref.
00:18:04 A ref where we have a function of sidebar and then we'll make this sidebar equal to the sidebar object that we created above.
00:18:12 I'll also add a tsignore right here, just so we don't have any TypeScript warnings.
00:18:18 Next, we can give it a created property.
00:18:21 So once this sidebar component gets created, what we want to do is automatically hide it.
00:18:26 So I'll say sidebar.hide.
00:18:29 Looks like our TypeScript will complain here a bit as well.
00:18:32 So what I'll do is remove these tsignores, and just at the top of the file, I will add a TS no check directive, which will make sure that no TypeScript
00:18:42 errors show for this file.
00:18:44 Then, we can also say close on document click.
00:18:47 This is very important to turn on for mobile sidebars, because if you click on a specific element in between the sidebar,
00:18:54 we want it to also automatically close.
00:18:56 We can also render the show backdrop to true, which will give it a bit of a background right here.
00:19:03 And then also we can give it a type equal to over because it's showing over the content.
00:19:09 And now the only thing we have to do is pass over the nav items component that we have created before for the regular sidebar.
00:19:17 And it'll also work here as well.
00:19:19 So just import nav items coming from nav items.
00:19:24 And you should be able to see the full desktop sidebar also works incredibly well on mobile, but now it also has some behaviors of a mobile sidebar.
00:19:33 such as you can click outside to close it.
00:19:35 Still, when you click on a specific element, it doesn't actually collapse itself, so you can see the page you're on.
00:19:41 Even though it actually does the redirect, you can see we're in the user table, but we cannot really reopen it anyway.
00:19:48 So there's definitely some more improvements we have to make to it.
00:19:51 One thing is taking this sidebar toggle outside of this direct click and turning it into a new function.
00:19:59 So we can pass it over into the nav items themselves.
00:20:02 So I'll simply copy this sidebar toggle and call it toggleSidebar.
00:20:07 So now right at the top, I can say const toggleSidebar.
00:20:12 is equal to a callback function within which we can just toggle that sidebar.
00:20:17 Now we're calling it right here on button click, but I'll also pass it as a prop over to the nav items.
00:20:25 So I'll say on handle click, toggle the sidebar.
00:20:29 So now we can head over into the nav items and we can accept this handle click as a prop, which will be of a type handle click.
00:20:40 a function that returns void, meaning nothing, and it'll also be optional.
00:20:46 So now we can use this handleClick when we're clicking something right here.
00:20:50 So I'll pass it as the onClick to this navItemDiv right here, where we have the classes.
00:20:56 I'll also add an onClick, and I'll say onClick handleClick.
00:21:02 So what this should do is when you click on a specific link, it should actually collapse the dashboard.
00:21:08 Oh, I see it doesn't do it just yet.
00:21:10 I think I know where the issue is.
00:21:12 Here, when we give it a reference, I should actually be making this sidebar object coming from Syncfusion equal to the ref,
00:21:19 not vice versa.
00:21:21 So what we need to do is switch it around so the sidebar object will be equal to the sidebar ref.
00:21:28 If we do this, you can notice that now it actually closes and you can reopen it.
00:21:33 Perfect.
00:21:34 We now have a mobile nav that allows us to navigate in between different pages.
00:21:39 So the last part of the layout that is shown across all the pages, can you see what it is?
00:21:45 We have the sidebar, we have the mobile sidebar and mobile, but what is that other element that also appears across all of the different pages?
00:21:53 Well, it's the header.
00:21:54 See, with a title, subtitle, and potentially an action button allowing us to do something for that specific page.
00:22:02 Almost every single dashboard has this.
00:22:04 Oftentimes, it is also called breadcrumbs because it tells you on which part of the dashboard you're on, such as Admin, Users,
00:22:11 or this could be Admin, Trips.
00:22:14 But in this case, since our dashboard is pretty simple, we just have a title, subtitle, and an action button.
00:22:20 So, let's implement it as well by creating a new component in the components folder, which I'll call header.tsx.
00:22:30 Run RAFCE, and for now, I'll just add it to the top of the dashboard page.
00:22:35 So right here, we have the page contents, but we'll wrap everything in a main.
00:22:39 So this is the main page with a class name equal to dashboard, and we'll also give it a class name of wrapper.
00:22:48 Within it, we'll display the header component coming from components header.
00:22:53 See, this is what I was telling you about.
00:22:55 If you don't export it from this components index, then you'll have to have a new import for every component.
00:23:02 But if I came in here and just exported it right here as header coming from header, in that case, you will just be able to import it like this by saying
00:23:15 import header from components.
00:23:17 Again, doesn't make a big difference now, but as you start importing more components into the file, it really makes your code that much cleaner.
00:23:25 This will be a self-glossing component, and we immediately know that we'll have to pass different props to it, such as the title and the description.
00:23:35 So title for now can be something like dynamic template string that'll say welcome.
00:23:42 And we can say maybe if a username exists.
00:23:46 So I'll create a new user right here.
00:23:48 const user is equal to an object that has a name of Adrian.
00:23:54 Of course, you can put your own name there and we'll say welcome if User?name exists, then use the name, else just say guest.
00:24:06 And we can also render an emoji of a wave right here at the end.
00:24:11 Near the title, we'll also render the description equal to...
00:24:15 We can do whatever we want to say here, but maybe something that explains that page we're on, such as track activity, trends,
00:24:22 and popular destinations in real time.
00:24:27 Perfect.
00:24:29 We can now copy this header, and we can also add it over to our second page, which is the All Users page.
00:24:37 As a matter of fact, we need to do the same thing right there.
00:24:40 Give it a main, a class name that says Dashboard, and wrapper.
00:24:46 Then we can render the header right here.
00:24:50 This time, we won't say welcome, we can say something like trips page, like this.
00:24:56 And then the description can be something like track users for now.
00:25:00 Of course, we can actually modify it later on.
00:25:03 Or not track users, that's a bit too creepy.
00:25:06 We can say something like check out our current users in real time.
00:25:13 And of course, below that, we have the actual page contents.
00:25:16 So this will be the all users page contents.
00:25:21 And then on the other one, that was the dashboard, we'll instead say dashboard page contents.
00:25:29 Perfect.
00:25:30 So now if we actually head over into our app, you'll see that we have the header and we have the dashboard page contents.
00:25:37 And if I move over into all users, we have the header, all users page contents.
00:25:42 But now we have to dive into the header component and accept those props to show the differences in between those pages.
00:25:49 So I'll immediately accept the title and the description.
00:25:54 We can actually define this as props So we can define an interface of props right at the top that'll have a title of a type string and a description of
00:26:06 a type string as well.
00:26:08 So now we can display the header component with a class name equal to header.
00:26:16 Within it, we can have an article because it contains two related pieces of info.
00:26:21 Within it, we can have an h1.
00:26:25 that'll display the title and below it, we'll have the p tag that'll display the description.
00:26:32 If you do this, you can now see Tripp's page, check out our current users.
00:26:36 But if I head over to dashboard, you can see welcome Adrian, track activity, trends, and popular destinations in real time.
00:26:42 Great.
00:26:43 Of course, the only thing remaining for us to do is to style it a bit better.
00:26:47 So let's do that by giving this H1 a class name equal to text-dark.
00:26:56 And we actually want to make this a bit more pronounced if we're on the home page.
00:27:02 See here, it shows up right here at the top, but on dashboard, we want to make it a bit larger.
00:27:07 So for that reason, I'll wrap this in a dynamic CN class name like this, and we need to properly close it as well.
00:27:15 So the TextStark 100 will always be there, but if the URL is home page, then we'll apply some different class names.
00:27:23 And how can we do that with React Router v7?
00:27:25 How can we figure out the path?
00:27:27 Well, it's super simple and very similar to Next.js.
00:27:30 I'll just say const location is equal to use location hook.
00:27:36 That's it.
00:27:36 You import it from React Router and you know the URL.
00:27:40 Oh, and let's not forget to import the CN as well from utils.
00:27:43 Okay, so now next to this default style, we can also check if the location.path name is triple equal to forward slash.
00:27:53 And if that is the case, we can give it a text of 2xl, on medium devices text of 4xl, and font dash bold.
00:28:02 But if we're not on the homepage, we can give it a text of xl, on medium text of 2xl, and font dash semi bold.
00:28:12 Of course, we have to properly close this now.
00:28:14 So now, if you compare the differences between this header size and this one right here, you won't be able to notice the difference.
00:28:22 That's because all of these are not on the homepage.
00:28:25 This is dashboard, and the other one is all users, where these ones need to be the same to have enough consistency in between the pages.
00:28:34 But I'll also teach you how to reuse this header on our public-facing website, whereas we want to make it much, much larger.
00:28:42 So that's where the difference will be.
00:28:43 But for now, we can also copy this H1 and paste it below, but change it to a P tag for the description.
00:28:54 This one will be text gray of 100, and font normal by default.
00:29:00 But if the path name is forward slash, it'll have text-base, and on medium devices, text-lg, and we don't need this font bold.
00:29:10 And if it's not on the homepage, we'll make it a bit smaller and give it a text-sm as well as on medium devices, text-lg.
00:29:20 And within it, instead of the title, we'll display the description.
00:29:24 So now we have a proper title and description right here.
00:29:27 So this is already looking great on mobile.
00:29:30 We have a fully functional mobile sidebar and it's starting to take the shape of the final application.
00:29:36 Of course, where dashboards truly shine is on desktop, where we have more screen real estate so we can see all of the different stats,
00:29:44 cards, tables, and charts.
00:29:46 So what do you say that we focus on the main dashboard page contents next?