In this chapter we're gonna go ahead and create the dashboard layout. And this is how it's going to look like. Organization switcher on the top, sidebar item groups in the middle, and in the footer we're going to have our user button. Let's start by adding some more Shazam components because right now our packages, UI, source components only has a button and input. To remind you how we add components, let me load the Monorepo documentation from ShatCN UI.
You go inside of CDAppsWeb and you run the command. So CDAppsWeb, make sure you are inside and then pnpm dlx shatcn at 2.9.2 because that is the version that I used to initialize this tutorial so that's why I'm using this version again. I'm going to add all components to save some time So we don't individually pick because we do need a lot of them but not really all of them. So I think this is a better solution. Let's just add all of them and then in the end we can remove those we don't use.
So let's go ahead and press enter here and I believe that we will overwrite the button and the input. I'm just not sure if it's going to ask us to do that or not. There we go. So do you want to overwrite? Sure.
Yeah, we can overwrite. And same thing for the other component that we have input I believe. And here we go. So it took me quite a lot to do this two minutes. So yes, if yours is still loading, it's normal.
So it added a bunch of components and it also updated a bunch of my packages here so you can see in pnpm lock we got a bunch of new stuff here and now when I added my form component It will automatically install the hook form resolvers and it's also going to install Zod and react hook form. I had some problems with that. I just want to tell you that in advance and I had to manually fix the versions. So just in case you try building the app or you see something weird with hook form resolvers, don't worry, I had that problem as well and if we encounter it, I will fix it. So let's go ahead now and let's develop the sidebar.
So the first thing I want to do is I want to go back in my root application. If you want to you can run pnpm install after this just to confirm everything is okay. And then let's do turbo dev and let's focus on our web application. Looks like it's building great. So let's go to localhost 3000 because this is where our main application is.
And it looks like it is building, works, perfect. Now let's go inside of apps, let's go inside of web. And instead of here, let's go inside of modules. And I'm going to create a dashboard module here and inside of here I'm going to create UI and then I'm going to create layouts and inside I will create a dashboard layout.vsx let's go ahead and export const dashboard layout here and I'm going to extract the children from here. Let's go ahead and type the children.
And let me just see, this is a react node. Inside of here, let's go ahead and render our auth guard like that. Organization guard like that. And then inside of here let's render main with class name flex flex1 flex-call and render the children inside. Like that.
And now you can go inside of your web app dashboard layout and you can simply replace this with dashboard layout. So we're going to develop the dashboard layout there. Like this. And you can remove the auth guard and the organization guard because we just moved it here. So right now nothing much should change within your application.
But now what you have to do is you have to import the sidebar provider and you can import the sidebar provider from workspace UI components sidebar because we just added this component and in here you have the sidebar provider. There we go. So after you have imported sidebar provider, let's go ahead and wrap our main inside of that. So sidebar provider. Now let's go ahead and do the following.
Let's add const cookie store to be await cookies and let's set the default open here to be cookie store dot get sidebar underscore state question mark dot value is equals to true instead of a string. This is important. Now let's go ahead and mark this as an asynchronous method. And let's import cookies from next headers. And make sure that you don't have useClient at the top or in your layout file here.
Now that you have that, go ahead and pass to your sidebar provider the default open value. This way, even during server-side rendering and server components, you will not have a weird flash that happens because you will be able to collapse your sidebar. And when you collapse it and refresh, for a second, it's going to expand and then it's going to read its local storage state and it's going to collapse back. And that just causes a weird effect. So by doing this, we make sure that even during server-side rendering, we know whether sidebar is collapsed or not.
Why sidebar state? Well, the answer is inside of the sidebar component in packages.ui.Source.Components. In here, you can find the sidebar cookie name sidebar underscore state so just double check that you are using the correct one. What we have to develop now is the dashboard sidebar component. So let's go ahead inside of dashboard UI in the apps web modules dashboard and go ahead and create components and inside add dashboard sidebar dot TSX.
Let's go ahead and mark this as use client and let's go ahead and import everything we're going to need. So we're going to need organization switcher and user button from clerk nextjs. Then we're going to need all the icons, right? Because if you remember here, we're going to need all of these icons to display. We can do that by importing them from Lucid React.
We already have this package installed thanks to Shazzy and UI. Credit card, inbox, layout, dashboard, library big, mic and palette icon. Then we're going to need to use both the image and link from next but individually next image and next link. And then use path name from next navigation. And now we need to import all the components from our sidebar component.
Sidebar, content, footer, group, group content, group label, header, menu, menu button, menu item, and sidebar rail from workspace UI components sidebar. And lastly, let's go ahead and import CN from workspace UI lib utils. And now let's go ahead and let's create our first array of items const customer support icons my apologies items let's render them in an array each item will have a title a url icon let's set this to be inbox icon, and badge. Let's go ahead and set this, actually no need for a badge, that's fine. And let's go ahead and give this a title of conversations the url forward slash conversations like that and then go ahead and copy it and change it to be knowledge base Forward slash files library big icon Now let's render those items so export cons dashboard sidebar like this is going to return a sidebar with a class name of group Make sure to capitalize the N in class name.
And in collapsible mode, it will only display the icon of each item. So when we collapse the sidebar, only the icon is going to be visible. Now let's go ahead and let's add the sidebar header. Now let's go ahead and inside of that header add the sidebar menu. Sidebar menu item.
And sidebar menu button. And go ahead and give it an as child property and size large. And inside render the organization switcher and add hide personal and skip invitation screen components. So now let's go back inside of the layout here, my apologies, inside of the dashboard layout component and just next to the main element render the dashboard sidebar And I like to use the modules sidebar UI dashboard, like that. And now you should have a big sidebar here and you should have the organization switcher available.
And right now there is no way to collapse this sidebar but we are going to add that soon and we're also not really displaying any items here. So let's go ahead and continue developing this until we can see some items so that we can start building this. So let's go ahead and go outside of the sidebar header and add sidebar content. Instead of sidebar content, let's mark this as customer support so we know what group this is. Now render the sidebar group, sidebar group label and write customer support.
And there we go. You now have a label customer support here. And now let's go ahead and let's add sidebar group content here. And let's go ahead and do sidebar menu and inside of here iterate over customer support items which we defined above. Get the individual item here and render sidebar menu item.
Give it a key of item.title, render sidebar menu button, give it an as child property, give it a tooltip property of item dot title. Title, let's just not misspell it. And also give it is active prop to be, let me just see, I think we have to develop is active yes so let's go ahead and just quickly develop is active by first getting the path name from use path name which we imported and then const is active will be a function which accepts the URL and it will simply check if the URL is root page, return path name is equal to that, otherwise return if path name starts with URL. So let's go ahead and use the isActive here item.URL like that Now inside of here you're going to use the link element give it an href of item.URL render item.icon here, give it a class name of size 4, and render this span item.title. And now, Looks like mine is collapsed and I think that the reason mine is collapsed is because I developed on localhost 3000.
So it could be that I have a cookie that collapsed them for me. I'm not 100 percent sure. Let me go ahead and check what is my cookie name sidebar state looks like I don't have it. Okay, so I'm not sure why mine is collapsed. I'm going to go ahead and this is what I'm going to do.
I'm going to go to the end of the sidebar here. Instead of dashboard sidebar. Right here and let's add sidebar rail. It's a self-closing tag. This should enable you to click in the edge of your sidebar and you should be able to open it and close it.
And now try refreshing. And it should preserve the state. So if you collapse it and refresh it should stay collapsed. So The way this works is thanks to this, thanks to cookies. In here, we store that so we know is it opened or is it closed.
And also make sure you're doing this in desktop mode. If you're too zoomed in, it's going to disappear because on mobile, it hides itself. Great. So now let's go ahead and expand this and let's continue developing. So now we can add some other items here instead of the dashboard sidebar.
Let's go to the top here. After customer support items, you can add configuration items. So a new array, exactly the same as the one above but with some new icons and some new elements. Widget customization leading to forward slash customization. Integrations leading to forward slash integrations.
Voice assistant leading to forward slash plugins forward slash WAPI. And make sure to use the proper icons. And now what we have to do is we have to render the same thing here. So let me go ahead and Let's copy the sidebar group and let's add an empty space here and let's paste another group. Change this to be configuration.
Change this to be configuration. And in here change this to be configuration items. I think right now, yeah, this says voice assistant. Now we are later going to change this to be a VAPI icon. For now, we can leave it as is.
I think this is okay for now, yeah. But later when we, we're going to filter this out and we're going to change this to be as in the screenshot, as you can see. We're going to use a VAPI icon, so it looks like a proper integration with some other platform. Now let's do the same for accounts and account items. So this will be much simpler.
So go at the top where your configuration items are and simply add account items. And then you just have to do the same thing, right? So go ahead and copy the last sidebar group here. Like so, add a space and change this to be account. Change this to be account and account items.
And now let's go here And there we go. Conversations, knowledge base, widget customization, integrations, voice assistant, plans and billing. So now what I want you to do is I want you to go outside of sidebar content and open up sidebar footer. And in here render the sidebar menu and let's go ahead inside and render sidebar menu item. Go ahead and render the user button component which is a self-closing tag And go ahead and give it a show name prop.
And now at the bottom, you will have your user button. But we have one problem with this, and that is when it's collapsed, the clert components don't look good. So all the other ones seem to integrate quite well as you can see but these ones seem to be a little bit problematic. So what we're going to do now is we're going to fix them starting with the organization switcher. So let's go ahead and focus on this component right now.
So we can use the appearance prop for the organization switcher. So let me go ahead and do that. After these two props go ahead and add appearance and open an object. Go ahead and select the elements object and first let's define the root box. Give it a full width and put exclamation point at the end.
This is equivalent to writing important. Right. So if I go ahead and add an exclamation point and hover, it looks like nothing shows when I hover. I'm not sure why this is usually when you have Tailwind CSS IntelliSense, it should be able to help you with class names, but maybe this is because of a monorepo structure. I don't know.
But basically just put an exclamation point and that will mark it as important which means it will override if there is another width set and same for height 8 and you can see that now when you refresh well you can't really see anything but the root box now extends up to here except it doesn't have a color. So now we're going to change the user button trigger which is the thing that we can currently see and that's what we're going to change to be with full as well. Let's see. Okay Still nothing is showing. So with full padding to and let's do hover BG sidebar accent like that.
Let me just check. Is anything here changing? I just want to make sure I'm not doing something incorrectly here. Okay, so let me just check organization switcher. The root box is definitely all the way to the end, but I think there is something with the sidebar that's making it like this.
So let me just check. The width is definitely overridden by width full. So I'm just going to continue developing and we're going to see okay so user button trigger now has with full padding to hover BG sidebar accent hover text sidebar accent foreground group data collapsible is equal to icon. Make sure you are writing all of this without any space. So this is all one thing.
When that is active give it a size of 8 and group data collapsible icon again give it a padding of 2 and now when it collapse okay I'm not sure why this is not doing anything here so let me just check my deepest apologies I am reading you completely incorrect things. This is not user button. For some reason I thought we were developing the user button. My deepest apologies. Let's remove the user button trigger because that's not what we need.
Let's go ahead and add avatar box just below the root box. My apologies again. Rounded, small. So make sure you add these two classes. I completely missed what component we were editing and I was telling you incorrect instructions.
So the one we need to target is OrganizationSwitcherTriggerComponent. Let's try it now. So with full justify start. Let's see. There we go.
You can see how the entire thing is now selected. My deepest apologies. I kept seeing that something is wrong but I wasn't sure what it was. Okay. And now let's do on group data collapsible icon.
Go ahead and change the size to be eight. And then you can copy this class name. Use it again and change the padding to be 2. And now when you collapse, it should look like this. There is still this caret here, don't worry, we will solve it, but you can see how Now it adapts to the rest of our app.
I think this looks much better already. Now let's continue developing this. So let's go ahead and give it the organization preview option. And in here we're going to do a similar thing. So you can just copy this group data collapsible icon because it's gonna be the same everywhere.
Give it justify center and gap two. So right now we only changed the gap when it's expanded. So it matches the gap of all the other items here. Then let's do organization preview text container. Again, go ahead and copy group data here.
Collapsible icon. And simply make it hidden. And after that, give it a text extra small, font medium, text sidebar foreground. So one collapsible icon only hidden everything else is independent. So let's go ahead and see how it looks now when you collapse the text button completely the test completely disappears.
And now let's go ahead and solve the caret. So the key for that is organization switcher trigger icon. Let's go ahead and copy the group data again. And make it hidden. And then let's use ML Auto.
And text sidebar. Foreground. And I think that now we finally get a beautiful effect. Perfect. It looks just like all the other icons and you can open it normally.
And it fills the whole width when active. Perfect. Now let's do the same thing for the user button, which is what I did initially, but I was telling you, invalid classes. So let's go down to the user button. Let's add appearance, elements.
And let's start with adding a root box. Full width and height 8. Again I don't think nothing will be visible now because we need the user button trigger. What we initially were doing. So full width and padding 2.
There we go. You can see how now full width is being taken and this is centered. Let's do on hover BG sidebar accent. So now when you hover you can have the same background as all of our other element so it matches. On hover text sidebar accent foreground.
Group data collapsible icon size 8 and you can copy this and besides size 8 also padding 2. So I think that already when you collapse ok not perfect let's continue developing let me just confirm that I didn't misspell the group data thingy. You can copy it from any of the ones above. But looks like it is the exact one. Yes, okay.
So now after user button trigger, let's do user button box. Full width. Flex row reverse. Justify. And And you can see that now I have reversed the user button icon to be on this side and the text to be on this side so it fits all the other elements here using flex slow reverse and justify end.
Now let's give the same gap as all the other elements and now let's use group data collapsible icon here to be justify center and text sidebar foreground. So we are getting much better. Perfect. Now let's go ahead and target user button outer identifier. PL will be zero.
Let's go ahead and use the group data again hidden and avatar box Let's give it the size of 4. And just like that we have created it exactly the same as our other ones and when collapsed it collapses nicely. Perfect! So that is exactly what we wanted. We now have a sidebar that will appear for each of these pages right here and we will be able to change our organizations now.
Let me just change this to something else. As you can see we can now change within our organizations from the sidebar here and you can also see how it exactly matches this the organization here and from here you will be able to manage your account or log out. Perfect. So let me see what else do we have to do. We added all the components.
We created the dashboard layout. We created a sidebar, groups, user button and organization switcher. We didn't do the empty pages so we could do that to end the chapter. And yes, I'm aware that the colors are a little bit different. Don't worry about that.
We're gonna have a special chapter called theming in which we are going to learn how to theme our projects properly. So let's go ahead and just create these empty pages for now. So I'm going to go inside of web, inside of app, inside of dashboard. And let's go ahead and do the following. I'm going to create conversations and inside page.tsx page conversations.
And now when you click on conversations you should be able to see conversations and this should be highlighted You can see how it's bold and it looks selected. And now let's go ahead and let me just remove the test page. We no longer need it. Copy conversations and change this to be files. Go inside of files and change this to be files.
And basically now go ahead and do that for each of our dashboard sidebar items here at the top. So we added conversations and we added files. Now let's do customizations and integrations. So just like this, customization page.tsx, integration page.tsx. So nothing special, We've already done this before.
And now let's also do plugins WAPI. So this one is a little bit different. That's why I want to do it with you. Inside of dashboard, create a new folder called plugins and then inside a new folder called wapi and then inside page.tsx that's how you create nested components whoops let's just do this wapi plugin And I think there's only one left and that is billing. So let's go ahead and copy files, rename it to billing.
Like so. And I believe that now every single one of our pages should be visitable. So billing should load billing, voice assistant should load WAPI, integrations, integrations, widget customization, knowledge base should be files and conversations should be conversations. Amazing, amazing job. So in the next chapter, we're going to add some theming.
So it looks like I screenshot it here Amazing. So we added empty pages. Now, let's go ahead and commit these changes and review our pull request So I'm going to add all of these changes and this will be 07 dashboard layout. I'm going to commit and then I'm going to open a new branch 07 dashboard layout. And I'm going to publish that branch.
If you ever accidentally push your changes without opening a new branch, don't worry. You don't have to follow the branches like me. I'm just doing it because it's much easier to keep track of your project and what's going on. And so that you can see what we actually did in this chapter, right? So now I'm going to open a new pull request and this will be a pretty big one, I suppose, because Code Rabbit will now review 57 files, but I'm going to try to get the point across as short as possible, because we know that what this chapter was about was Sidebar.
And here we have the CodeRabbit summary. We introduced a comprehensive set of UI components, including all the way from sidebar to tooltip, basically all Shazzy and UI components. But here's what we actually developed ourselves. We added a responsive and collapsible dashboard sidebar with navigation, as well as user and organization management. And we also added new dashboard pages for every single item on that dashboard.
And in here it says that we provided a mobile deduction hook. So that was all thanks to Shazian UI CLI tool. We didn't do this manually. So for this reason it really makes no sense to go through all of this individually because all of these components are mostly added by the CLI tool, except well this I misspelled knowledge base so in the next chapter I will make sure that I correct my typo here. Great catch by CodeRabbit.
And in here, Yes, this is a good tip. We should probably export the sidebar cookie name from the sidebar component. So you can see how it searched through my entire code base and it found out that you can find sidebar state as a constant sidebar cookie name inside of my new sidebar component by ShadCN. So that is actually quite impressive because that's the first thought I had when I wrote this in a literal string. I thought I should probably export the constant and in here it tells me to do that.
So that's one thing we can do for sure. But everything else here is I don't want to change it even though it's probably a good suggestion simply because this is the CLI tool and I don't want to mess with this components if they work. So I'm going to merge the pull request and let's go ahead and wrap up this chapter. Let's go back to main and let's synchronize changes. And once you synchronize your changes, go ahead and open graph and in here you will have your new pull request.
Amazing, amazing job. Let's go ahead and mark this as completed as well and see you in the next chapter.