Now let's go ahead and let's modify our navbar. So it has some more features like an actual search bar and also looks a bit better on mobile mode, where we are also going to have an organization switcher here. So let's go ahead and find our navbar component. We can find that inside of underscore components navbar.tsx right here. And let's remove this bg-green-500 from here.
We no longer need that and let's remove BG yellow 500 from here as well. And first things first let's go ahead and let's create the search input component right here. So I'm gonna go ahead and do that inside of the underscore components here so search-input.tsx it's going to be a client component and let's also export const search input here and let's return a div search input. Like that. And now go back inside of the navbar and instead of the text search, you can add search input here from dot slash search input.
And right now this will only be visible on desktop so make sure that you are expanded or zoomed out enough so that you can see the search input here. Alright so now before we continue developing the search input I want to install two packages So let's go ahead and let's install query string. And let's install usehooks-ts. None of these are strictly required. They are just faster for me to use inside of this tutorial.
You can of course use native URL search params or you can build your own hook if you want to. Great, so let's go inside of the search input here and let's import everything we need. So we need QS from query string. We need search from Lucid React. We need use debounce from use hooks dash TS, which we've just installed.
We need use router from next slash navigation. Whenever you're importing user router, don't accidentally import it from the router because that does not work in the app folder. So that only works in the pages folder. And now let's go ahead and import everything we need from React. So that's going to be the change event.
We're also going to use effect and we're going to use state. And one more thing that I forgot to add is the actual input component. So npx chatc and UI at latest. Let me just expand this as much as I can. Add inputs like this.
So we need an input component. So npx chat CNUI at latest. Let me just expand this as much as I can. Add inputs like this. So we need an input component.
Let's do npm run dev again. Let's refresh localhost here. And then what we're going to do is we're going to give this div a class name of pool width and a relative. And let's add a search icon here and let's add an input here. And you can import input from components UI input like I did right here.
Great, so now if I expand this, there we go, we can see the search icon and we can see an input. So now let's align them together so it looks better. So first things first, I want to style the input accordingly. So let's give this a class name of PoolWidth. But let's limit how wide it can go by limiting into 516 pixels, which is just my random value that I found out looks the best.
You can, of course, modify it. And let's give it a padding left of 9, so it has a space for the icon to fit in. So I'm going to give this search icon a class name of absolute top one and a half left three transform minus translate dash y one and a half text muted foreground height four and width four So just make sure that this is minus translate minus Y, right? Because this also works, but you need to use minus. So it does the opposite of this, and then it's centered in the middle.
Great! And let's go ahead and give this input a placeholder of search boards. Placeholder... Placeholder without a typo like that. And there we go you can see how we now have our search here I can even zoom in a little bit and you can see how we have a nice little icon here and you can see how we have enough space both to write and to actually render the icon perfect and now let's modify it so that once we write something and after a debounce we added that to the URL query just as we did with the favorites true like this so we're gonna add a little search here so we can do that thanks to the change event use effect use state use the bounce query string and use router So let's go ahead and let's get the router.
Then let's go ahead and let's set the value and setValue to be useState and by default let's make it an empty string. And then let's debounce the value using useDebounce. And let's pass in the value and the amount of delay, which for me is going to be half a second. And then let's do const handle change to take in the event, which is a type of change event. And in pointy brackets, it accepts the HTML input element.
And then in here, we're very simply going to set the value to be event.target.value. And then let's go ahead and write the use effect. And let's add the dependency array to use the debounced value. So not the value, only the debounced value, but also the router, because we're going to need that to redirect the user. Now let's generate the new URL using queryString.stringifyURL.
The URL is going to be slash and the query is very simply going to be search and pass in the debounced value inside. And I also like to pass in these options as the third argument, sorry the second argument actually. Skip empty string true and skip null true. So we are never passing those in the URL. And then you can do router.push and paste that URL inside.
And all you have to do is assign this handle change to the input here. So on change and passing the value. So it's a controlled input. So now if I try and type something that's gonna appear inside of my URL. So I'm gonna write test here and there we go in my URL.
I have a query search test. Perfect. Right now that isn't doing anything, but later we're gonna use that to change what we are seeing right here on the boards. Perfect. So now what I wanna do is I wanna modify how this looks when I'm on mobile so I want to add an organization switcher here which will push this to this side right here.
Let's go back inside of the navbar component right here and right here after we do the search input I want to open a div with a class name, block on small devices, on large devices is going to be hidden and it's also going to take full space when visible so you can see how this already on the mobile mode took up this space right here and pushed my user button to the end here so you can see how on desktop it's still everything is the same but on mobile now my user button is pushed all the way to the side because of this div and what we're gonna render inside is actually the same thing that we are rendering inside of our organization sidebar So go back inside of the organization sidebar and find this organization switcher which we've modified. So it looks better. So go ahead and copy it. Go back inside of the navbar and paste it here. And you can import the organization switcher from clerk next to JS as well.
There we go. And let's just confirm that everything can stay the same. So display flex makes sense. Justify content center makes sense. Align items center makes sense.
The width 100% makes sense. But let's also add a max width the same way we did for our search input. So I'm going to give this a max width of three hundred and sixty seven pixels because I found that to be. You can see how it doesn't expand longer than this. Right.
So it kind of has the same behavior as our search where it stops expanding at some point because otherwise it just looks weird taking up the entire space. Great. And now what I want to do is I want to add a button here to invite members inside of any organization that we are in. And let's go ahead and do that. We're gonna have to create a new component for that.
So let's go ahead inside of components here and let's create a new file called invite-button.tsx. And let's go ahead and import plus from lucid react let's import organization profile from clerk-next.js and let's go ahead and let's import add components UI dialog and let's get the dialog, let's get the content and something to open the dialog with so dialog, dialog content and dialog trigger and let's also import a button component from components UI button and then let's export const invite button and very simply whoops we're gonna go ahead and render the dialogue, dialogue trigger, we're gonna give it an as child prop and it's going to wrap a button from chat CNUI which is gonna render the plus icon and invite members text and let's give this invite all right and let's give this plus a class name of height 4 width 4 and margin right of 2 and let's give this button a variant of outline and then very simply in the dialogue content we're going to render the organization profile like that so now if we save this file and go back inside of the navbar component. We can add this after our div wrapping the organization switcher.
So I'm going to add invite button from dot slash invite button like this. So the same way we imported the search input and there we go, we now have invite members but you can see that the div doesn't really match the size of this component so we can resolve that by going back inside of the invite button here and let's go ahead and give the dialogue content some props. So class name is going to be zero padding. BG is going to be transparent. Border is going to be none.
And max width is going to be 880 pixels like that. So now if you go ahead and look at it there we go perfect so now you can always click on invite members here and that's going to take you to the members page right here and you can easily add new invitations great but here's the thing I only want to show this if the user has an active organization. So if they are not in any organization, for example, if I go here and if I remove this organization right now, right? If I did this, there we go, you can see how this will say no organization. So I think that, yes, you can see how this is now an empty thing because it doesn't know to which organization are we supposed to add someone to.
So what we're gonna do is we're only gonna display that in the nav bar if we have an active organization. And we can do that using the use organization hook from Clerk Next.js so let's get the use organization hook from here and let me just collapse this elements and in here I'm very simply gonna add the organization use organization and we are only going to render the invite button if we have an organization like that. So now if you take a look at it, we should not be having this. Let me just refresh so I can confirm or maybe this will pick a random organization here. Let's take a look.
I think I need to destructure the organization. My apologies. Yes. So I need to destructure the organization from the hook. There we go.
So if we don't have an active organization, the invite button is not shown. But if we go ahead and select a random organization, there we go, we can click on invite members here. Perfect. So we have the working search, we have the working user button, we have the invite, we can switch to favorites, we have organization switchers, we even have a special view on mobile. Perfect.
So now we are ready to go ahead and actually start creating some empty states for our favorites and our team boards and then slowly we're going to create a database schema and start creating our boards. Great, great job!