Now that we have our navbar set up, let's go ahead and let's create the equivalent functionality and by that I pretty much mean just the UI for this sidebar right here. So we're gonna have some similar elements right here in this corner. So let's go ahead inside of our source folder, our features, editor, components and inside of here we can find the sidebar component. And now inside of here what I want to do is I just want to start by adding an unordered list element and giving it a class name of flex and flex call meaning that it's gonna go in a column one below another and now what we have to do is we have to go ahead and create a new component called sidebarItem.tsx so we don't have to copy and paste a bunch of elements every time. So let's go ahead and prepare the types for this.
So we're gonna have a LucidIcon which is the generic type for icons from Lucid React. I believe you can also import it like this. So now it's precisely the type. We are also gonna need CN from libutils. So we already have this.
We never wrote this but we got this when we installed the ShadCNUI and this is used to merge or to dynamically enable and disable Tailwind classes in a safe way. Now let's also add a button component from components UI button. Let's create an interface sidebar item props. Let's give it an icon of lucid icon, a label which will be a string, is active which will be an optional boolean and onClick which will be a void method. Let's export const sidebarItem and let's quickly assign the props here, so sidebarItemProps and let's return a button component which will render the icon.
Now you're wondering where do we get the icon from? Well we can actually remap this prop to a capital I So we can write icon and then we can add an alias icon like this. Because if you want to use something as an element it needs to have an uppercase letter. So we can create an alias. And for the rest of the stuff we can just pass them as they are.
So isActive and onClick. There we go. And now this icon works just fine. Let's go ahead and give this button an onClick method of onClick. So we're just passing or forwarding the prop here.
Let's go ahead and write the class name here. It's gonna be dynamic so open curly brackets and write CN. In the first argument of the CN we're gonna write the default classes. So I'm gonna use full width, full height here. I'm gonna make an aspect video here.
Adding of three, adding on the y-axis of four, flex, flex column and rounded none. And then as the second argument, I'm going to add if is active. In that case, I'm just going to slightly modify the background of my button. So BG muted and text primary. So let me zoom out so you can see how this looks like.
So cn is a function which can accept as many arguments as possible. So if you... There we go, you can see how it spreads the inputs. So there can be as many arguments as you want and you can also add these dynamic ones like is active in that case change it to this or you can of course do this without the CN class but this helps us with proper merging of Tailwind classes because Tailwind classes can override one another So if you're not careful you might end up with styles which you did not expect. And this CN is a very simple and lightweight util which helps us a lot in the long run.
And now let's go ahead and let's give some styles to this icon here. So I want to give this a class name of size 5 stroke 2 and shrink 0. And below that I'm gonna add a span element which will very simply render our label. And let's give this span a class name of margin top 2 and text xs like this. Great!
Let's go ahead and try and render something in the sidebar now. So I'm gonna add the sidebar item. I'm just going to change my import. You don't have to do this, but I really like when it's like this. Now I have to pass in a couple of props here.
So icon here will be layout template from Lucid React. Label will be design. Is active will be false for now. And on click will just be an empty arrow method Let's save this and there we go. You can see how now we have right here this design button So I'm gonna go ahead now and style it even further So if I go inside of sidebar item, I believe that we can just change the variant of this to ghost and it should look better.
There we go. Now let's go ahead and change what happens if I turn this from is active false to true and there we go. You can see how it kind of stays selected. Perfect. So just make sure you add the variant ghost to the sidebar item.
And now let's go ahead and let's add other elements we need. So I'm going to go ahead and import every icon we are going to use. So we're going to need an image icon, We're going to need a pencil, a presentation, a settings, shapes, sparkle, sparkles, and type. Like this. Also one quick tip about Lucid React.
So each of these icons also has an alternative import. So you can, if you want to, you can import image or you can import image icon. So you can import pencil or pencil icon. So this is useful because image is, for example, something that comes from, you know, next image like this, it's actually a default expert, right? So then if you had two of these, you would run into a problem, right?
So then you would either have to do image as image icon something like this or very simply they they already give you an alternative image icon so if you had you know pencil you would do the same thing just pencil icon right So that's if you ever wonder why I somehow sometimes use the icon name instead of just image, it's because of that. Alright, so now I have all the icons I need, so what I can do now is I can copy and paste this sidebar item and prepare my other elements. So the next one here is going to be my image, my apologies the image icon right. This is going to say image and the onClick can stay the same. And I just want to add isActive false explicitly.
So I know I have to change this later. All right, below the image icon, we're going to use type. And this will say text. Below the type, we're going to use the shapes with the shapes label. Below the shapes, we're going to add sparkles with the AI label.
So this will be our AI model. Below that we're gonna finally have the settings with the settings icon and label. There we go so this is our sidebar So we will now be able to click on this individual elements and that's going to open another sidebar here which will give us even more options to work with. Excellent. What I want to do now is I want to create the functionality for this on clicks right here because they are quite simple.
We are just going to control this using a simple set state. So here's what I want to do. I want to create an interface for my sidebar here. So let me go ahead and create an interface sidebar props and I'm going to accept an active tool which will for now just be a string and then on change active tool will accept a tool which is also a string and it returns a void. So let's go ahead and do the following.
Let's go ahead and get the sidebar props, get the active tool and onChange active tool. And now what I want to do is I want to go through each of these elements and add the proper is active and on click here. So the design or the layout template icon will be active if the active tool is equal to templates. But let me stop right here. There is one thing I think we need to do before we continue with this and I'm going to show you why in a second.
Let's go ahead and do the following. Inside of our source feature editor components, let's close the components folder and let's stay inside of the editor and let's create types.ts like this. Inside of here, let's export type active tool. And Inside of here, we're gonna write all possible tools. So we're gonna have the select tool, we're gonna have shapes, we're going to have text, we're going to have images, we're gonna have draw, We're gonna have fill, we're gonna have stroke-color, stroke-width, font, opacity, Filter, Settings, AI, Remove-BG, and Templates.
And let me just format this perhaps, there we go. So you can also add, you can add the line even in the first one right here. Right, so when you hover over your active tool it should be all of these possible options. So I want you to write this first and then I want you to go back to sidebar here and instead of using the string option here let's use the active tool which we now have in our types. So features editor types.
There we go. So that's what I want and then we also want that right here. So now if you accidentally write a typo here you're going to get an error because there is no overlap. So now we can safely continue writing this. So the design will be active if the active tool is templates.
And the on click here will be called the on change active tool. Again, you can now see we also have the auto complete here, templates. There we go. So that's what I wanted to achieve. So let me just copy these two and now I'm going to replace these.
So this will be images. Images. Let's copy again. Let's replace the text one. So active tool here is text and it's changing the active tool to text.
For the shapes it's the same things. Make sure you don't have a typo like I do but don't worry because you will get an error and then in here we have AI and in here we have the settings. There we go. Perfect. And you've probably noticed that there are many more tools in here than we have options here.
That's because there will be different ways to activate specific tools, not just from the sidebar. Great. So now what we have to do is we have to go back to where we actually render our sidebar. So that's in Features -> Editor -> Components -> Editor right here and this is where we render the sidebar and you can see we already have some errors here because we are not giving our sidebar the proper tools to work with. So let's go ahead and let's start by going above everything here.
I'm gonna go ahead and create an active tool, set active tool, use state and let's first of all import the use state from react so just make sure you have this. Now let's assign active tool as the type for this state. Like this. And let's go ahead and define the default one, which in my case will be the select tool. So that's going to be the default tool when user loads the editor, like this.
And now let's go ahead and let's define the onChangeActiveTool method. So const onChangeActiveTool will be useCallback from React. So just make sure you've imported use callback. We're going to be using this inside of a use callback because I want to put this inside of some use effects later on so I need it memorized. And we're going to accept the prop called tool which will be a type of active tool.
If tool is equal to active tool, in that case, what we're gonna do is write return set active tool, select. So if you click two times on the same tool, we're just gonna reset back to select as an easy, you know, deselect option. And let's add active tool to the props here. There we go. And now what I wanna do is I wanna add a couple of more options here.
So I'm just gonna say, if tool is equal to draw, I'm not gonna do anything yet. I'm just gonna add it to do enable draw mode because we can't do this yet, but I don't want to forget to do this later. And then again if active tool is equal to draw, we do disable draw mode. And then we're just going to add set active tool to the tool which we passed. There we go.
So it's important that you do a return here. Right? If the tool is the exact same to the currently active tool, we are not going to go further. We're not going to do this logic. Make sure you add return here.
There we go. So we now have onChangeActiveTool. Let's go ahead and add this to our sidebar now. So I'm going to go ahead and give the active tool here. And on change active tool will be on change active tool.
There we go. No more errors. And let's try it out now. So if I go ahead and refresh this and select design, there we go. You can see how design stays selected.
If I click on image, image stays selected. Same thing if I click on settings, AI, shapes, text, right? So I can even play around and click here and you can see how this stays grayed out. Same thing on the shapes here. What I want to do now is I also want to enable this in the navbar.
When I click here I want this to be selected. So this is our select tool. And what should happen when I click on an already selected one, it should be unselected. Perfect. So now image is selected.
I click again, it's unselected. Perfect. Let's go ahead and let's quickly revisit our navbar component in Features, Editor, Components, Navbar right here. And I want to do the same thing. So similar to as we did with our sidebar component let's create an interface navbar prox and let's accept an active tool to be a type of active tool from dot dot slash types or features editor types like this and I'm just going to move this along with the logo here besides that we are also going to have onChangeActiveTool as a method which accepts a tool to be a type of active tool and it returns a void like this.
So that's it for the types for now. Now bar props here, we extract the active tool and on change active tool and then let's go ahead and in here I've added add functionality but that's not for now. So we want to find this, our button with the mouse pointer click inside. So I can now remove these two to-dos and do the following. So on click here, we'll very simply do on change active tool to select and for the class name we have to add dynamic cn library so just make sure you add the import for cn from libutils let me just move it here there we go cn from libutils the same thing we did in our sidebar I believe and now what we want here is the following if we have an active tool and if active tool is select in that case I want to render a specific background bg-gray 100 like this.
So CN does not have to have the first classes as default. You don't have to do it like this right. Any class can be dynamic. I mean any argument can be the dynamic class. And let's try it out now.
So now if I just refresh, oh, it's not working because in the editor, we are not passing anything to the navbar. So go back to the editor component and it actually needs to have the same props as the sidebar. And there we go. You can see that now when I completely refresh my page in the nav bar, my select button is active by default. But if I click on design, for example, it stops being active.
If I click on it again, it's active again. So same logic for all of these other ones right here. Perfect. So that's what I wanted us to achieve. What we're gonna do next is we're gonna go ahead and we're gonna explore some simplest elements we can add here such as shapes for example.
So we want to create the shapes sidebar which will allow us to add more rectangles to the screen. And then I want to play around and finally enable this toolbar which will allow us to enable even more tools and I also want to play around with some canvas events. For example, when I randomly click outside I want to reset back to the select icon. Nevertheless, great, great job!