All right, so now that we have our navbar for this organization page right here, it's time for us to create a layout for our organization route which is going to push the content below the navbar and also render a little sidebar here so we can choose between each organization that we have. So first thing that I want to do is go back inside of the app folder, platform, inside of our dashboard and here in the organization folder create a new file layout.tsx so just make sure that it's not inside of organization ID we're gonna have a separate layout for that as well and as you can see we have this error because we're not exporting anything from layout So let's write const organizationLayout from here. We already know that we can extract the children so let's do that and let's assign a proper type to them and then we can just go ahead and render main, render children inside and export default organization layout. Great! As you can see now nothing should change but the error should go away.
Now let's give this main element a class name of padding top 20 and as you can see now this content has been pushed below our navbar here you probably forgot that we even had that it is inside of this organization ID page right here we have a text organization page but inside of this layout where we rendered the navbar that has been hidden so now when we created this layout inside of the organization folder we brought it back here. Besides this let's also give it a medium device where it's gonna be PT24 so even further down and PX is gonna be 4 and max width is gonna be 6XL so if you forgot what that is well that's the limit to how far something will go in resizing, right? So let's go ahead and give it a 2xl, so if we are on a large monitor then max resizing is going to be Wscreen XL and MX Auto to make sure that it doesn't overflow. There we go, you can see how now I cannot resize past a certain point. Great.
And now let's go ahead and wrap this children inside of a div and let's give this div a class name of plex and gap x7 and then in here we're gonna open a new div with a class name of W-64 shrink-0 hidden and MD block. So this is gonna be a wrapper where we are going to render the sidebar. So for now I'm gonna leave a comment for that. So this is defining how wide that sidebar is going to be and shrink0 is saying that when we collapse our screen, so not on mobile, right? On mobile as you can see it's hidden.
It becomes visible on medium devices. So this shrink zero is only actually gonna relate to this screens, right? So you can see how this organization page content is shrinking, right? When I collapse my screen. What we want to ensure with shrink zero is that this sidebar content never changes is fixed with which we decided right here.
Great. And now before we start and build this entire sidebar thing I want you to do the following. So I want you to go ahead and create a new organization. Let's call this I don't know another organization. Let's click create and we're not going to invite anyone.
And I want you to take a look at something. So right now if I go ahead and switch from the organization here you can see that my URL changes as well right so if I choose another you can see that I have the new URL right here the organization has changed but what if I copy the URL then change the organization and then paste it here what happens I should technically be on this organization because that's the URL right but I am not So we're going to create a little component which is going to actively take a look at our URL and then programmatically change the active organization. So let's go ahead and create that. And we're going to do that by creating a new layout inside of the organization ID folder so leave this like this for now and then inside of organization ID create a layout.tsx and let's go ahead and name this const organization ID layout. You already know that we can extract the children.
Let's give them a type of React React node. And in here, let's just, we can actually return a fragment, which is going to render the children and export default organization ID layout just save that and you should have no errors and nothing should change and now what we are going to do is we're going to create a component called organization control but we're going to spell it as org control so it's shorter, great! And now let's go ahead and create this. So inside of OrganizationID here, create a new folder, underscore components and inside create a new file org-control.dsx let's mark this as use client let's go ahead and import use effect from react let's go ahead and import use params from next slash navigation and let's go ahead and import use organization list from from clerk next.js and then export const org control it's gonna have nothing in its props and in here we're gonna return null because this is purely going to be used to do some things in the use effect. So first let's get the params from useParams.
Then let's go ahead and let's the structure set active from useOrganizationList and you already guessed it we can use this to change the organization programmatically so what we're gonna do is we're gonna open up the use effect call whoops in the dependency array we're gonna pass in the set active and params dot organization ID so it's only gonna change it's only gonna be called once this changes and let's go ahead and write if we don't have set active we can just break the function and then set active and let's say organization is going to be params dot organization organization ID as a string there we go And now let's go back inside of this layout where we attempted to use that, but we don't have the import and let's just add this import. So a few things that I want you to confirm. Make sure inside the org control component you did not misspell params.organizationid. As you can see we don't have any types here so we're just spelled it out right we hope that we spelled it out correctly. We never defined which are the types of these params.
So make sure you didn't misspell this and make sure that it matches this folder variable right here otherwise you're gonna have some issues. So now let's test out that thing that I was talking about. So I'm gonna choose this test organization. I'm gonna copy the URL. I'm gonna switch to another and as you can see now another is selected but if I change my URL manually and press ENTER there we go it switched to test.
You can see for a second it was another and then our org control component activated and it switched to test. Perfect! So that's what I wanted us to do before we go on to creating the sidebar because the sidebar is also going to just push to the URL. So instead of us calling the set active every single time we do route push we can create a component like this which is actively taking a look at the parameters inside of our URL and if it changes it will change the organization for us. Great job!
So first I want us to head into the terminal and install a couple of packages which we're going to need to create this sidebar component. Let's go ahead inside of the terminal. I'm just going to shut down the app and I'm going to write npm install usehooks-ts. This is going to be a compilation of useful hooks for us to use which are type safe. And then we're going to go ahead and call npx chatcn-ui at latest add skeleton so we're gonna make sure that we have the skeleton component and we're also gonna add in the accordion so accordion like this make sure you have this two installed perfect And then you can go ahead and run npm run dev.
Like that. Perfect. Now let's head back inside of our organization layout. So right here where I wrote the comment sidebar. And in here now I'm gonna render the actual sidebar so if I save I'm going to get an error here just make sure you refresh your localhost every time you shut down the app and rerun it again so there we go now you can see that I have an error.
So let's go ahead inside of the dashboard components right here where we have the navbar. So why here? Why not create a components inside of this folder if that's where we use it? Well, because we're gonna reuse it in the navbar as well in a different component called MobileSidebar. You can see that I have a comment here for MobileSidebar but we're gonna get onto that later.
So for now, find the dashboard folder, find the underscore components where you have the navbar and in here create sidebar.tsx let's go ahead and mark this as use client and let's export const sidebar and just return a div saying sidebar great and Now we can head back into this organizational layout where we have an error for importing sidebar and we can safely now add it not from Lucid React but from ./.components sidebar. Great if you save you should now no longer have an error and when you expand you should have a little text which says sidebar here which is only visible on desktop devices so if you collapse like this it's not going to be visible. Alright so now let's go ahead and let's start developing this So first I want to create an interface sidebar props Which is gonna hold the storage key and I'm gonna explain why we're gonna need the storage key Once we actually use the accordion component So let's go ahead and extract that storage key. So just assign the prop sidebar props here and let's extract the storage key. All right, so storage key is gonna be used inside of our accordion.
That's because the accordion can be expanded or collapsed and it can get pretty annoying. The fact that accordion collapses itself after a re-render. So if we change a specific active organization all the sidebar items are going to get collapsed. So that's why we're gonna have this storage key and we're going to use local storage to keep track of what was opened and what wasn't. So let's go ahead and add all the necessary imports we're gonna need to create this component.
So we're gonna need some link component from next slash link. We're gonna need plus icon from Lucid React. We're going to need use local storage from use hooks TS which we just installed and we're gonna need use organization and use organization list from clerk next.js and then let's go ahead and let's import the button from add slash components ui button let's go ahead and let's import the separator if we have it we don't have separator so I forgot about that let's head back inside of our terminal I'm just gonna open a new one here and write npx chat-cn-ui at latest add separator whoops let me just delete all of this and write it myself. Separator. Like that.
So just make sure you have this component installed. Great. Make sure you have your project running. And now let's try again. Import separator.
Make sure you don't import it from Radix make sure you always import from add slash components whenever Radix is offered in your imports you did something wrong right so make sure you never do that let's go ahead and let's import skeleton from components UI skeleton and let's import our accordion again you can see I have imports from radix and I have imports from add slash components so always make sure you're using the components not Radix because you're not gonna easily notice what's wrong, right? There are not gonna be any errors in your code. You're just gonna notice that your component is unstyled and it doesn't work as it should. And 99% of the case is because you imported something from Radix. Great, perfect.
So now we have this and let's go ahead now and let's add all the hooks we're going to need and all the other stuff So first let's create a state which is going to be connected to our local storage which is going to keep track of which accordion is expanded and which one is not. So const expanded, setExpanded and this useLocalStorage works very similar to useState. So you can see that we have the expanded, setExpanded and now we're gonna add useLocalStorage here like that and let's pass in the storage key and let's pass in the default object which is an empty object and now let's go ahead and just give a default value to this storage key in case we don't pass it to the sidebar. So in this case I'm gonna use the letter T to indicate that this is our Trello project. T sidebar state.
So why am I even using this as a prop? Why not just hard code that here? Well, as I said, we're going to reuse the sidebar in our drawer for mobile devices. And it can get pretty inconsistent if you use the same storage key for both. So we're gonna have something like the mobile sidebar state once we create our mobile sidebar.
So for now just pass in this and now what I want to do is give this local storage a defined type of what to expect inside so that's gonna be an object so record with string and any like that perfect so now that we have that let's go ahead and let's get the current active organization so const organization is gonna be an alias we're gonna alias it to active organization so if you don't know when working with objects when you destructure things by default if I just did whoops so if I just did this then we access that organization right if I want to I can render the organization like this right but you can also do this like active organization or whatever you want you can rename it to whatever you want and then you would use active organization in your components. So that's what the LES does. And let's get the ActiveOrganization from useOrganization. And while we are here, let's also extract the isLoaded prop. So isLoaded, and we're gonna remap that to isLoadedOrganization.org for short and now below this constant let's also add another hook from the organization list so const and we're gonna go ahead and extract user memberships isLoaded which we are going to remap to isLoadedOrganizationList and we're gonna get that from useOrganizationList Perfect and let me just de-indent this.
All right, and now inside of this organization list, I'm gonna write user memberships infinite true. So if you're wondering, how do I know that we have to write this infinite true very simply this is from the clerk nextjs documentation right so this isn't something anyone would expect you to know right you simply have to take a look at their organization hooks documentation and from there you can see exactly why we need it and what it does basically it's kind of a pagination thing. Alright so now that we have this let's create a constant called default accordion value so const default accordion value is gonna return an array of string and we're gonna call object keys over the current expanded constant so this one right here so object keys expanded and we're gonna call reduce we're gonna get the accumulator which is gonna be a type of array of strings. And we're also gonna have a key, which is gonna be a string itself. And then we're gonna open an object.
And if expanded, if the current key is expanded, in that case, we're gonna push that to the array so key like that and let's go ahead and return the accumulator and let's give it a default value of an empty array like that. Perfect! Now that we have the default accordion value let's go ahead and let's add a function which is going to actually add something to the expanded list when we click on it. So const onExpand is going to take in the ID of the organization which is a string and all we're gonna do is set expanded get the current value open up an immediate object spread the current value and then just add that ID and we're gonna make it the opposite of what it currently is. So expanded ID.
So if it was true it's gonna be false, if it was false it's gonna be true. Great! And now let's go ahead and let's create our loading state. So if we have not loaded organization or if we have not loaded organization list or if user memberships.isLoading, sorry, this is not, this one We write without this Exclamation point like that. So if either of those is loading in that case, let's go ahead and let's return for now We can just write a skeleton.
It doesn't matter. We imported it Later, we're gonna actually style it to look something to look like something. Great! So let's just go ahead and refresh to see if we are seeing anything. Great!
You can see how for a second nothing is rendered because we have a little skeleton but I mean it's not really visible yet but don't worry we're gonna go ahead and style it later. All I want to ensure is that for a second our sidebar is loading. Great! And now let's go ahead and let's actually style this div here. So first of all I'm gonna wrap this entire thing inside of a fragment and then I want to go inside of the div and give it a class name of font medium, text extra small, flex items center and margin bottom of 1.
Then I'm gonna write a span here which is going to say workspaces and the class name PL-4. And then let's add our button component which we imported and inside add a link which we imported as well. Let's give this link an href of slash select dash org and inside we're gonna render our plus icon from Lucid React. All of the things basically which we imported here. Great, all right and let's give this plus icon a class name of h-4 and w-4 and then Let's give this button an as child prop, a type of button, a size of icon, a variant of ghost and a class name of ML auto so it is pushed to the right.
Great! And now let's go ahead and see if we can already take a look in it. We can. There we go. So now we have our workspaces text and when I click here I'm redirected to create a new organization or select one.
Perfect. So now let's go ahead and actually render our organizations here. So go outside of this div which renders this workspace and a button. So right at the end of our fragment. And in here go ahead and add the accordion component which we already imported right here.
Again make sure you don't accidentally use the Radix one and let's go ahead and give it a type of multiple so multiple accordions can be active at the same time. Let's give it a default value of default accordion value. So yes I kind of forgot to explain what we're actually doing here so the values the way we keep values in here in this expanded is not exactly compatible to the way default values are expected inside of the accordion component. So that's why we create this little constant here. Default accordion value to reduce over that expanded object which we have.
You can see it's an object right and this object is going to look like something like let me just write here something like I don't know basically my organization id true or false. So this is what that object looks like, right? So basically what we're doing here is we're iterating over that entire object and we're creating an array of active IDs. So we are turning them from that object. Let me write a comment here.
So we are turning it from this object which was 1, 2, 3 true into an array which just going to hold 1, 2, 3. So that's what this default accordion value does. And the reason again why we need that is because that is what this accordion component expects in the default value. You can see when I hover it expects a string of an array of strings or Undefined completely. Great.
And let's give it a class name of space Y2 Perfect. And then inside let's go ahead and let's do userMemberships.data.map and let's immediately destructure the individual organization from here and let's go ahead and for now let's add a paragraph organization.id like that and give it a key of organization.id and let's see if we can now take a look there we go. You can see because we have two organizations we are rendering two organizations id here. Perfect! So now we're gonna create a component called nav item which is actually going to render that organization in a nicer way with a little image and some additional actions.
So that component is going to be called nav item. So let's go ahead and return this paragraph. So we remove that paragraph and instead render the nav item component which we don't have yet but we're going to have in a moment. Let's give it a key of organization.id let's give it an is active prop to be if active organization.id is equal to current organization in this array id let's go ahead and give it is expanded prop to be if we have this organization ID inside of the expanded object so organization.id and let's also pass in the entire organization organization and let's add onExpand to be onExpand so we should have all of those props here great and now let's go inside of this underscore components folder where we have navbar and the sidebar itself and create a nav-item.tsx Perfect. So let's mark this as use client as well and let's go ahead and export const navItem and return a div navItem and then we can go back inside of the sidebar and we can import the nav item from .slash nav item and I'm gonna separate this like that.
Perfect. Let's head back inside of the nav item and let's go ahead and give it some props. So interface nav item props is going to have an isExpanded which is a boolean, isActive which is a boolean as well, it's going to have organization which for now let's say any, we're going to create a type for it in a moment let's also add on expand which is a function which accepts an id which is a string and returns a void and now let's go ahead and create a type organization what's important for us is that it has a id, a slug, an image url and a name which is a string and now let's use this organization instead of this any type and let's also export type organization so we can use it elsewhere great, so now let's go ahead and assign those props, so nav item props and let's extract isExpanded, isActive and organization and onExpand. Great! And now head back inside of the sidebar where we rendered the nav item and as you can see we have a little error here so let's just fix that by adding as organization and import organization from .slash nav item let me show you that right here so from nav item I'm importing the component itself and the organization type which we just made exportable like this.
There we go and now you should no longer have any errors here. Perfect, so let's go ahead and let's style this. So instead of a div, this is actually going to be an accordion item from add slash components UI accordion so let me show you make sure you have this imported again not from radix give it a value of organization dot ID give it a class name of border none And then let's go ahead and add accordion trigger from components accordion. Let me just collapse this ones. Great, so accordion trigger.
And inside, let's go ahead and give this a non-click which is an arrow function which calls on expand and passes in the organization ID. Let's also go ahead and give it a class name and this is gonna be dynamic so make sure you open curly brackets and import the CN library. So I imported CN library right here I'm just going to move it to the top. All right so this CN library is going to have some default classes which are going to be flex items center gap x2 padding of 1.5 text dash neutral dash 700 rounded MD hover bg dash neutral dash 500 slash 10 transition text dash start no dash underline hover bg-neutral-500-10 transition text-start no-underline so those classes and we're also gonna add an additional hover no underline as well. Great and then go ahead and add a comma and now we're gonna write some dynamic classes so if this current accordion which represents an organization is active and if it's not expanded in that case we're gonna render an indicator for the user to know that it is active so BG sky 500 slash 10 and text sky 700 great And then inside of this accordion trigger let's go ahead and let's create a div, let's give it a class name of flex items center and gap X2 let's add a new div with a class name of w7 and h7 and a relative and inside we're going to render an image component from next slash image so let me show you where I imported next slash image and I'm just moving it to the top here.
So let's give this image a fill property. Let's give it a source of organization.imageURL. Let's give it an alt of organization and let's give it a class name of rounded small and object cover and I think that already we should be seeing something and as you can see I have a little error here so this happens when you add an image to the next image component but you don't modify the config as you can see in the error right here. So what you have to do is find what it says for the hostname it's probably gonna be exactly the same for you as it is for me but you know just in case something changes in the future find this image clerk.com and now let's head inside of next config to allow next.js to use images from that source so let's go ahead inside of next.config.js here and let's write images, remote patterns and let's open an object so protocol is gonna be HTTPS and hostname is going to be image.clerk.com like that, great and now what I recommend you do is just restart your application so I'm gonna do that npm run dev and then I'm just going to refresh my localhost and while that is refreshing I'm going to go back inside of my nav item component where I just rendered the image.
And let's see, there we go. You can see how nice this looks now. We have a little image and you can see how because this organization is our selected organization it has a bluish color right until we expand it then it doesn't have a bluish color so that's defined right here in this dynamic is active and it's not expanded and if you're wondering why does it lose a color, why did I make it like that? Well, it's going to make sense in a second when you see the actual content which is going to be inside of what's expanded. Perfect.
So let's just try and switch to another organization and there we go. You can see now the top one is bluish. Perfect, exactly what we want. But besides rendering the image, we're also going to render the actual organization name. So outside of the div, which is wrapping an image, add a span, which is going to render the organization name and give this a class name which is going to be font-medium and text-small.
Great, let's see that. There we go. You can see how nice this looks now. Perfect. So what I want to do now is create the actual accordion content.
But in order to do that I first want to create an actual routes array for that. So let's go ahead and first let's import all the icons which we're gonna need from Lucid React for that. So go ahead and import from Lucid React the following icons. Activity, We're going to need the credit card. We're going to need layout and settings.
So those are the icons which we are going to use for our content. And now let's go inside of the nav item before we return this. And in here let's go ahead and let's write const routes to be an array of objects and each object is going to have a label first one is going to be boards with an icon of layout and he's going to have a class name of h4 h-4 w-4 and mr of 2 and it's gonna have an href and open backticks for this one and also let's add a comma here so we don't have that error and the href is gonna go to slash organization slash specific organization ID. So basically the default page. And then let's go ahead and just copy these three items here.
The second object's label is going to be activity and the icon we're going to use is activity and it's going to go to organization, organization id slash activity. Great and let's go ahead and copy and paste this. The third one is going to be settings, it's going to use the icon settings and it's going to go to slash settings. So this part pretty much always stays the same. Let's copy this again And this one is going to say billing, the icon we're going to use is credit card and it's going to go to slash billing.
Great. And while we are here, let's also go ahead and import our router and our path name here. So const router from useRouter from next navigation. So let me just show you that quickly. There we go.
UseRouter from next slash navigation. Make sure you add that. Also just a quick tip. Sometimes if you use like this auto imports, it can happen that it imports router from next slash router. And you can see that there's no error here, right?
But you can no longer use this. If you're using the app router, you have to use next slash navigation. So whenever you're using user router, if you have some weird errors and nothing is read in the code Just make sure that your user router is coming from next slash navigation and besides user router. Let's immediately import use path name And now let's go ahead and add path name use path name Great. And now let's go ahead and add path name, use path name, great and now let's go ahead and let's add our const on click to accept an href which is a string and router.push that very same href.
Great! And now we can finally go inside of, outside of accordion trigger and render the accordion content. Again from add slash components UI accordion. So I added it right here. Make sure you have it as well.
And let's go ahead and give this accordion content a class name of padding top one, text dash neutral dash 700, like that. And then let's go ahead and render routes.map get the individual route and go ahead and render a button component from add slash components UI button let me just show you how I imported that right here all right and let's go ahead and give this button a key of route.label or maybe href would be better. A size is going to be smaller. OnClick is going to be an arrow function which calls the onClick and passes in the route href and class name is gonna be dynamic so the default ones are gonna be wfull.normal justify start pl10 and margin bottom of 1 and then we're gonna have if path name is equal to route.href then we're gonna make it bluish so bg sky 500 slash 10 and text sky 700 great And let's give it a variant of ghost. And now finally inside of this button we can just render route.icon So route.icon.
Don't accidentally do router, right? I wrote that a couple of times. So route.label Great! And let's test this out now. There we go and as you can see when I expand now it makes sense right this is why when I expand this loses the color because this one is active right trust me if both of them are blue it just looks weird so this looks much better perfect and here's the cool thing when I refresh you can see that because we use the use local storage, this accordion stays open.
So the user doesn't have to always manually expand that especially if they're gonna have a bunch of workspaces and perhaps organized exactly you know the ones they want to see open and if you try and click on this you're gonna get a 404 which is good because it's working So just check in the URL and you can see we go to slash settings here, you know, check the billing, you can see we go to slash billing. And if you click on the boards itself, nothing's going to change. But if you click on the boards inside of another organization, you can see that it switches to that organization. So take a look at my navbar. Now it says test here and this is blue color.
But when I click on boards here, now this is blue color and this has changed to that workspace. Great! So you finished this little sidebar here. So now what I want to create is a way to open that sidebar if we are on mobile because right now there's no way, well first of all there's no space to render that sidebar. Technically we could like render it on the top and then display the content on the bottom but I really don't like that solution.
So what we're gonna do is we're gonna head back inside of our app folder, platform, dashboard components here in the navbar. You can see I left a little to-do here to create a mobile sidebar. So if you don't have this command to help you find that, first of all go inside of this navbar component and find this logo component and outside of this two divs, so just the first line inside of your nav element. That's where we're going to render the mobile sidebar, which we're gonna create now. First thing I want to create is a hook, which is going to control the state of that mobile sidebar.
So whether it's open, whether it's closed, and also we're gonna use it so that when we click on a specific board in the sidebar, the whole drawer or the sidebar, whatever you wanna call it, closes. Because in my previous tutorials, some people told me that when I create this mobile sidebars, it's not exactly the best user experience because it kind of stays open after you change the route. So that's why this time I made an attempt to improve that. Of course there are many ways you can do that but you know in the specific way we're doing it I kind of feel like we have the most options by using a state to control that. There are of course like what's the name...
Proper components to do that from chat.cn but it simply kind of feels like too much work and spaghetti code to do it. I don't know. You can of course try it yourself. So this is what we're gonna do. We're gonna go inside of the terminal.
I'm just gonna close it and I'm gonna write npm install to stunt. So make sure you have that installed and we're also going to need a sheet component so let's go ahead and let's add npx-shatsien-ui-latest-add-sheet like this Make sure you have that package and this and then you can npm run dev again. Great. So let's go ahead and let's create a new folder called hooks and inside of this folder create a new file use-mobile-sidebar.ts like that and let's import create from zustand so the package which we just installed let's create a type for this so mobile-sidebar-store is going to have a property isOpen which is a boolean is going to have a function onOpen which is a very simple function and the same goes for onClose. And then export const useMobileSidebar is gonna be create and let's give it a type of MobileSidebarStore let's extract the set and then immediately return an object like that so make sure you wrap it inside of additional parentheses.
If you've never seen this syntax, let me just briefly explain. If you do this, this opens a function. So you would have to do return and then an object. But if you want to skip that you can just open parentheses and then an object and this tells javascript you know okay so this is immediately returning an object and let's add is open to be false let's add on open to be a function which calls the set which we extracted from the props here and it's gonna set isOpen to be true and we need onClose and then our errors are gonna go away and we need isOpen to be false here. Great, so we have that and now let's go back inside of our navbar component, so app, platform, dashboard components, navbar and in here I'm removing this comment again so the first item inside of your nav element that's where it should be.
Let's add the mobile sidebar and if we save of course we're going to get a little error as soon as my local host refreshes So let's go inside of the underscore components so where all of our new items are and let's add mobile sidebar TSX. Let's mark it as used client and export const mobile sidebar and let's return a div saying mobile sidebar and now we can go back inside of the navbar and we can now safely import mobile sidebar. Great! So let's go back inside of the mobile sidebar now and first thing I want to do is I want to add that hook so first we're gonna get extract on open which is gonna be use a mobile sidebar we're gonna get this state and we're directly going to add state is open sorry on open we're gonna copy this two more times the second one is gonna be on close and the last one is gonna be is open there we go So we have the three states here. Perfect.
And now let's go ahead and let's add the path name. Use path name from next slash navigation. And let's also add is mounted and set is mounted to be controlled from use state. So this is going to help us to prevent hydration errors, especially when working with sustained states and components like models or sheet components. So let me just align my imports a bit so these are the global ones.
Great. Alright, so now let's finish doing this isMounted trick here. So I'm gonna call useEffect and I'm gonna set isMounted to be true. And then I'm gonna write if it's not mounted just return null. So why am I doing this?
So in Next.js, even if you mark something as a use client, that doesn't exactly mean that it's not going to be server-side rendered, right? There is one... I mean you can correct me if I'm wrong but this is how I understood it and why these hydration errors even happen when using useClient components. So as far as I understand each component even if it is in useClient is going to be server-side rendered at least the first iteration of it, right? So what happens when you're using this models and sheets and this type of components is that on server side, it has a specific state like closed right and then on the client side it's suddenly opened and that creates a hydration error right and it just doesn't look nice and it's very confusing to you why is it happening and you know how to fix it.
So how does using this use state is mounted and this use effect actually help? Well one thing that you can do to guarantee that a specific component is only gonna be rendered on the client so never on the server not even server-side rendered is by using useEffect because useEffect will not run in that server-side rendering iteration so basically what we are telling this component is if this is mounted has not changed to true meaning that if we have never reached this initial use effect we don't render anything because obviously this is still running on the server right But then when it reaches this useEffect it changes it to true and then we skip this and just render our component. So I hope this kind of cleared it up. You can also Google a very good blog post called the Perils of Hydration and inside of there you can see an in-depth explanation of what I just said with probably a much better way of explaining than I just did. Great, so I hope that kind of cleared it up.
Alright, and now let's go ahead and let's add a new use effect here which is going to be called every time a path name changes and let's also add on close here so we can call it properly. And very simply, we're just gonna call onClose. Basically what this means is that whenever our URL changes, mobile sidebar will close. So we're gonna use that, that when we click on a specific item in a sidebar, the router is going to push, the URL is going to change and our sidebar is going to be closed. So with this way we don't have to manually call on close every single time.
Great, so now that we have all of those things Let's go ahead and change this div into a fragment. Let's remove this text and let's render a button component from components UI button. And inside I want to render the menu icon from Lucid React, so make sure you have that imported. Let's give this menu a class name of H4NW4. Give this button an on click to be on open.
Let's give this class name a block and MD hidden. So this is only visible on mobile devices, right? When it reaches a medium screen, it's immediately hidden because on medium screens, we have that big sidebar here on the side. So no need for this additional one. And let's go ahead and give it a variant of ghost and the size small.
Great, and then below this button let's open up a sheet component from Components UI right here. So again, make sure you don't accidentally import it from Radix. And while we are here, let's also add the content. Great, So let's go ahead now and let's render the content. And inside all I want to render is the sidebar from ./.sidebar.
So we're gonna reuse that entire component. And let's go ahead and pass some props and some styles before we try it out. So the sidebar needs to have a different storage key. So T sidebar mobile state. Like that.
Just so it differs from the desktop state and let's give this sheet content a side of left and the class name of padding 2 and padding top of 10 and this sheet is going to have an open of open Sorry is open and on open change is gonna be on close Just like that. So let's try it out. So make sure you are on mobile mode click here and There we go. You can see how when I click here it changes the organization and it closes. Beautiful, beautiful job.
Great, so just one quick thing I want to do here. These two buttons seem just a bit too close to one another. So I'm going to go ahead and give this one margin right to... There we go, that looks just a tiny bit better perfect so you've finished the entire thing you can see you can do anything on mobile as you can do it on desktop as well great great job So next thing we're gonna do is we're gonna create the settings page for each of our organization.