So now let's go ahead and create the ability to change the color of our selected layer. In order to do that we're gonna have to create a component called Selection Tools which is going to appear right above our selected component. So let's go back inside of our canvas component. So that's in board, board ID, components, canvas. And right here outside of the SVG parent and below the toolbar, let's go ahead and create our new component which is going to be called the selection tools.
And now let's go ahead and pass in the camera prop which is going to be our camera and set last used color which is going to be set last used color like this. Now let's go inside of the underscore components folder and let's create our selection tools.tsx. Let's mark this as use client and let's go ahead and create an interface selection tool tools props to accept the camera which is a type of camera from types canvas. And let's use set last used color to accept a prop color, whoops, which we also import from types canvas and it simply returns a void. And then we can export const selection tools.
And very simply, let's also memoize this. So we can use memo from React. And let's add selection tools display name to be selection tools just so we get rid of the error. And in here we can return a div selection tools and now let's just go ahead and destructure our props which is the camera and set last used color here and let's assign the props selection tool props selection tools props there we go Now we can go back inside of our canvas component and import selection tools from .slash selection tools the same way we did with the cursors presence for example. Now let's focus on being inside of this selection tools right here.
Let's go ahead and decide whether we should render this or not. So const selection is gonna come from useSelf, which we can import from liveBlocks.config. And let's go ahead and get self using me, me.presence.selection like that. And now we are going to reuse our hook useSelectionBounds. So let's write const selectionBounds to be useSelectionBounds which we have from hooks useSelectionBounds right here where we have this big bounding box function.
So make sure you have that. If you don't, you can always visit my GitHub. And now that we have the selection bounds here, let's first do, if there are no selection bounds, we can simply break and return null, because there's nothing we can calculate here. Now let's define the x coordinate which is going to be selectionBounds.width divided by 2 plus selectionBounds.x plus camera.x and y coordinate is simply going to be selection bounds.y plus camera.y like this. And now let's go ahead and give this div a class name of absolute padding 3, rounded, extra large, background white, shadow small, border flex and select None.
And now let's go ahead and pass in the style. Transform. Open backticks. Translate. And in here, let's go ahead and let's pass the first argument to be calculate.
Go ahead and write x in pixels minus 50% like this and then the second is going to be calculate again Y value minus 16 in pixels minus 100% like that. And let's see if we can already see this. So if I select something, There we go. You can see how it appears nicely above and follows my selection right here and you can see how it works even when I move the camera around. Perfect!
So using this we are now going to be able to create a component called Color Picker which is then going to change the used color for this specific layer. So let's go ahead and let's do that. So I'm going to replace this with a ColorPicker component and I'm going to pass in the onChange prop which for now is just gonna be an empty object. So let's go inside here and create the color picker. Let's mark this as useClient and let's go ahead and create an interface ColorPickerProps onChange very simply it's gonna accept a color which is a type of color from types canvas and return a void and let's export onColorPicker here This one is very simply going to accept on change from our color picker props here.
And let's return a div color picker for now, just so we can go back inside of our selection tools and import the color picker from dot slash color picker like this. And now when I click here, it should say color picker. So we can continue working in the color picker component now. So let's go ahead and quickly create a color picker, sorry, a color button. So let's first do interface color button props to be on click and it will send the selected color, which we already have imported from types canvas and the current color representing that button.
And now let's do const colorButton here. And in here, we're going to use those colorButton props. And we are going to extract on click and the color like that. Great, so we have the color button here prepared so we can return a div color button. So now inside of the color picker we're going to use that color button.
So let's go ahead and give this div a class name flex-flex-wrap-gap-to-items-center max-width of 164 pixels padding-right of 2 margin-right of 2 border-right and border-neutral 200 and Inside of here. I'm gonna render a color button like this and we can copy and paste it a couple of times and there we go. You can now see that we can render multiple color buttons here. So now obviously we're going to style this better so it actually shows just a small picker for the next color. So let me just remove this and let's work with one example for now so onClick for now is just gonna be an empty well we can pass in the actual onChange right we have it in the props onChange and the color can be whatever we define in RGB values.
So for example, R can be 243, then G can be 82, and then B can be 35, for example. And now let's go ahead and use this inside of the color button. And let me just show something here so we can see it. So we have color button here and now we're going to use those props to actually turn this into something. So first things first, I want to use the actual button element.
I'm going to go ahead and give it a class name of width 8, height 8, items center, flex justify center, hover opacity 75 and transition. Let's give it an on click. To be an arrow function which calls the onClick and passes in the current color for this button. And inside of this button, we're going to have a div, the class name of H8W8RoundedMediumBorder, border neutral 300. And more importantly than that, it's gonna have a style component, background, which is gonna use our color to CSS, which we've created when we needed to transfer the fill property in the rectangle so it's from Libby Utils right here color to CSS and it simply transfers our RGB object into a hex code So let's use that color to CSS and let's pass in the color.
And this can be a self-closing tag. It doesn't need an end tag like this. And there we go. You can now see our beautiful color right here. So this is what I recommend you do next.
If you want it you can now create as many of these color buttons as you want here or if you want the exact same ones you can go and find inside of my repository, inside of board.id components, simply find the color picker inside of my repository here. And in here you can just copy all of these color buttons which I have prepared for you. Right, So there's no point in writing all of this out if you want to change the colors to something else. So I'm going to replace all of my color buttons here with those. There we go.
Let me zoom out. So all of this should be in one line like this. And there we go. These are the colors that I like. They're kind of flat colors.
Great. And now, right now if you click on them, nothing happens. So what we have to do is we have to actually create this method inside of our selection tools for the onChange of the color picker. So inside of the selection tools here, let's go ahead and let's create a method called set fill. So const set fill is going to be use mutation from live blocks config right here.
And let me just go ahead and return this. And we are going to extract from use mutation here Storage And we are also going to extract fill Which is a type of color Which you can import from types canvas and now let's go ahead and do const live layers storage get layers and then set last used color to be the new fill color which we've just selected and then we're going to do for the selection which we loaded right here above for the layer we are selecting for each id live layers dot get id question mark in case it doesn't exist dot set the fill value is going to be pill, like that. And let's go ahead and make sure that we added selection and set last used color in the dependency array of useMutation from LiveKit from LiveBlocks. Let's go ahead and use setFill here now and let's simply pass it here for the onChange. And let's go ahead and see if this is already working.
So if I select this one and change the color, there we go. We can now officially change colors of our layers. Great! So how and why does this work? Well, you have to ensure that inside of your app folder board ID components in the rectangle here you are properly using the fill extraction from the layer.
So make sure that you didn't leave this as hard-coded black, right? We only use the black color, well, initially, but also if for any reason we don't have the fill property. Great! So we've wrapped that up and now what I want to do is I want to create a quick little additional action here to delete the layer because it's going to be much simpler to do than our actions to move layers up and down which is going to be in a separate chapter. So let's go inside of our hooks folder and let's create a new hook called useDeleteLayers.ts Let's import useSelf from LiveBlocks.config and useMutation from LiveBlocks.config as well and export const useDeleteLayers.
First, let's get the selection so we know which layers to delete. So we get me, me.presence.selection. And then let's simply return useMutation here. Let's prepare it like that. And in here, we're gonna go ahead and extract the storage and set my presence from the first argument my presence like that so let's get live layers to be storage.getLayers and const liveLayerId to be storage.getLayerId and now we're going to do four const id of selection which we have liveLayers.deleteId and then const index liveLayers.
Sorry liveLayerIds.indexOfId which we are trying to remove we're gonna check if index is not minus one, meaning that it exists in the list of array. LiveLayerIds.delete using that index. And then what we're going to do outside of this for loop is set my presence selection to be an empty array and add to history true. Like that. So now let's go ahead back inside of our selection tools component where we just added the set fill for the color picker.
And now what we can do is we can import that hook. So const delete layers. Use delete layers from hooks use delete layers. Make sure you added the import hooks use delete layers like that. And now what we have to do is simply add a little button here.
So let me go ahead and import the following. We need to import the button component from components UI button and we also need to import a hint from components hint and I would also like to import Trash2 from Lucid React as an icon. Great. So now let's go just below the color picker and let's add a div here with a a class name flex-item-center padding-left of 2 margin-left of 2 border-left and border-neutral 200 let's add our hint component and inside we're going to render our button component. So let's give the hint a label of delete very simply and let's give the button an icon of trash too and let's give it a variant of word, size of icon and on click delete layers.
So make sure you've added delete layers right here from use delete layers. And there we go. And as you can see, we clearly have like extra borders here. That's because in between here, there are going to be two more buttons for a position change so let's try it out if I click delete oh it looks like it is deleting but our previous one which I think is because of something missing inside of our dependencies array okay so I'm gonna go ahead and quickly debug this. So let's try this.
I didn't change anything yet, but I think it's inside of the use delete layers. My dependency array is empty, but I rely on the selection from here. So let's go ahead and ensure that we pass in the selection inside of my use mutation right here. So this selection gets used. This is inside of use delete layers.
And nothing else is changed. Let's try it out now and there we go. Now exactly what I click gets deleted. Perfect! So we have this working, we can change colors, we can delete, we can move, we can resize in every direction.
Perfect! What we have to do next is moving layers up and down above another and then we're gonna go ahead and wrap it up with our selection net so that we can select multiple items at once and then we're gonna go ahead and create a little pen effect and then easily add all other elements. Great, great job.