Solution #1
Links and Resources
Transcript
[00:00:04] Welcome to the advent of CSS.
[00:00:06] Woohoo! Since this is the first challenge, I thought I'd include just a little bit of information about getting started. So within the notes, you should have links to GitHub. So I'm going to start on this Day zero. We have a storybook and tailwinds set up and you can either download the zip to get the code on your machine or you can grab the link for this repo and clone it or you can even click on Open in Gitpod and this will open up basically a version of VS Code within your browser So I'm going to copy this particular repo and I'm gonna pull up my terminal and I'm running warp here make this a little bit bigger I'm gonna go into my projects directory and I'm gonna Just create a folder here for Redwood, and I'm going to say get clone and paste in that URL. So that's going to grab everything. Now if I navigate into that particular directory, I'm going to run Yarn install and that will download all of the dependencies that I need for my project So this might take a hot minute to download everything, but you only have to do this once.
[00:01:16] Okay, then if you want to pull up your Redwood project You can just say yarn Redwood dev and we'll pull up that splash page but we're actually going to do a majority of our work within storybook and
[00:01:26] Storybook is a first class citizen within Redwood, so there's no additional setup that you need to do. So, it looks like I probably already have a Redwood project running on port 7910. I'm just going to go ahead and say yes, but just know that you're probably going to look at Port 7910 and I'm looking at 7911.
[00:01:44] Okay, so right now my storybook is empty because I don't have any stories. That's totally fine. I'm going to come back over to the terminal and I'm going to open up my project within VS Code. For this first challenge, what we want to do is we want to create our own custom icon component. And we're going to use SVGs, and there are several benefits here, but by creating an SVG sprite, that file can be cached, we have all of our icons within a single file, and we can change the colors and the size within CSS, which is going to be huge as we continue to use this component in other places.
[00:02:20] And if you're interested in learning more about SVGs, you can check out my YouTube channel. So, shameless plug. But I have several videos all about using SVGs. I'm kind of a snob about them.
[00:02:30] Let's start by going into figma and here under the pages I have a style guide and if you don't see that You can toggle this up and down and then click on style guide. And you'll see here that I have a whole bunch of icons. Now the trick to dealing with icons is that you want them all to be the same size.
[00:02:47] This just makes it easier to manipulate within the code. So within Figma, I can command click on this to select an element. Now you'll notice that I selected a specific path, but I want to select the entire icon. And you'll see that that is 24 by 24. So that is the measurement that we want all of our icons to be is 24 by 24.
[00:03:09] So as you're selecting these, make sure that you're grabbing the correct frame there. And once you have it, you can come down here on the right side and say export. Now if you don't see this bar, perhaps your screen looks like this.
[00:03:22] You can click on the plus button to export, and then I'm going to say SVG, and then you can export that to your downloads folder, to your desktop, wherever. Now if you don't want to deal with Figma at all, that's perfectly fine. Within the project files, I provided all of the SVGs, and there should be 14 of them.
[00:03:40] So I'm going to grab all of them. And let's stick this inside of my scripts folder. I'm going to create a new folder here and call this SVG icons. The reason I'm sticking this in the scripts folder is because eventually with the Advent of JavaScript, you'll create a script to automate this whole process.
[00:03:57] But right now we're going to do it all by hand. So here I have all of my SVG icons. And then in Redwood, anything that goes into the web public folder will automatically get exported and be available in the frontend. So I'm going to create a new folder here and I'm going to call this icons and I'm going to create a new file inside called sprite. svg.
[00:04:21] So this file will contain all of my icons and I'm going to use symbols in order to serve up the correct image. So first we need to start with an initial framework. So I'm going to start with an SVG tag.
[00:04:35] So I'll have an opening and a closing tag. Then I'm also going to give this an attribute of XML N S and say HTTP www. w3. org 2000 slash SVG. So it knows what version of SVG we're working with and what the spec is.
[00:04:53] Then inside, I'm going to create a definitions tag. So we'll say defs, and then inside I'm going to add a symbol tag. So every single icon that we create will have its own symbol that we can reference. Now in order to reference that, we need to give it an ID. So I'm going to pass in the first icon that we're going to create, which is going to be our calendar.
[00:05:17] Now we also need to establish a view box. And you can check out my YouTube channel for more information about ViewBox, another shameless plug. But basically, you can think of ViewBox as establishing the window that you'll see. Now if you jump over to the calendar. svg, you'll notice that there is already a view box provided. So you can think of this as the XY coordinate for the top left and then the XY coordinate of the bottom right. I'm just going to copy and paste this into our symbol.
[00:05:46] Then I'm also going to create a title tag here, and this will just keep things nice and accessible so that the browser knows that this is going to be a calendar icon. Now I'm going to come back over to our SVG here, and I'm going to copy our entire path tag, and I'm going to paste that into our sprite.
[00:06:05] Now, in order to be able to control the color for our icon, we need to get rid of this inline attribute for the fill.
[00:06:12] And the reason being is that because this is an inline attribute, it will override whatever CSS we pass it. So I'm going to delete that. And then we actually don't need this fill rule or this clip rule attribute.
[00:06:24] So I'm going to delete those as well.
[00:06:26] I'm going to give this a save now before we build out all 14 icons I want to have something to look at to make sure that we are headed on the right track So, one thing that you can do within Redwood is you can generate components through the command line tool.
[00:06:40] So I'm going to go back over to warp, and I'm going to say yarn redwood generate component, and I'm going to call my component an icon. Hit enter, and this will generate three different files for me. Oh, check that out. I need to upgrade Redwood. So this is awesome. And actually this is a great plug for Redwood because they do handle all the package updates for you. You don't have to worry about that yourself. And it literally is as easy as running Yarn Redwood upgrade.
[00:07:07] So I'm going to run that command, it'll upgrade everything for me,
[00:07:11] So now I'm just going to hit the up arrow a couple times to make sure that we're actually running that generate component icon. So it said that it already existed, so it looks like it did run before it told us about the upgrade. Awesome. So now inside of our web directory, We have a source directory and a components directory and here's our icon and you can see it generated a stories file, a test file and an icon component.
[00:07:34] So if we look at this in the browser, I'm going to hit refresh, you can already see that here's the icon component that we just generated and there's some boilerplate code inside that we will overwrite.
[00:07:45] So, if you are new to React, don't let this scare you. The important thing that you need to know for these challenges is what is inside this return statement. This looks just like HTML. And so we are going to write HTML and CSS. That's all you need to worry about.
[00:08:01] There's two features that you should be aware of. So you can only return a single thing. So, for example, if I have another div inside that I'm trying to return, you'll see I have an error here, and it's also erroring out within Storybook.
[00:08:16] You get this weird message that says that adjacent JSX elements must be wrapped in an enclosing tag. So all that's saying is you have two things here and we can only return one. If this is the code that you are trying to return, what you can do is you can wrap it with an empty tag. This is called a fragment inside React.
[00:08:35] And then the problem goes away. The other thing that you need to be aware of is when you're writing styles, instead of saying class equals, whatever your tailwind stuff is, you should say class name.
[00:08:47] And that's camel cased. And then inside you can say text is red 500 and write your tail in classes just as you would if you're writing vanilla HTML and CSS. So now if I come back over the browser, you can see that I now have red text.
[00:09:00] Okay,
[00:09:01] So within VS Code, I'm going to delete this, and I want to reference our SVG. And for now, I'm going to say that I want the width to be 24. And the height to be 24. And then I'm going to say that I want to use, and I'm going to use an href to say what I want it to use.
[00:09:20] Then inside, I'm going to say that I want to use, and I'm going to use an href to point to our SVG sprite that we created. So, we've already talked about how we stuck this in the public directory. This will be available on the front end as just slash icons slash sprite dot svg.
[00:09:39] And then what we can do, since we've created a symbol now for our calendar, is I can just give this a hashtag or a pound sign and say calendar. If I hit save, now if I come back over to my browser, you'll see there is our icon component that we just created. Pretty cool, right? We'll continue to create all of these icons, but just to recap, make sure I'm not moving too fast here, Within the scripts directory, we created an svg icons directory and put all of our svgs there. And that's simply because within Advent of JavaScript, we will later create a script to generate this particular file for us.
[00:10:14] So that's why it's in a script. We'll create a script later. on the JavaScript side.
[00:10:18] Next, within the public directory, we created an icons folder with a sprite. svg and we gave it an svg tag. Told it what spec we're using, and then we created a definitions block, and inside we have a symbol for our icon.
[00:10:33] We gave it the ID of what we're working with, so that we can reference it here within our component. And we also passed in the view box, so that it understands the window that we're working with. I gave it a title tag, so that it's nice and accessible. And then I copied the path tag from our SVG that we exported out of Figma.
[00:10:52] And then we removed all the unnecessary attributes. So we removed the fill, and we removed that clip path. Then we generated a icon component from the command line, using the tools that Redwood provides. And we simply set up our SVG tag, then we told it that we wanted to use our sprite that we created specifically referencing our calendar icon. Now if we come back to our sprite, let's create another one. So I'm going to scroll up here to the top let's create one for our check icon.
[00:11:22] So within our SVG sprite. I'm going to copy our symbol block, paste that in, and then I'm going to replace our ID here for calendar with check, and within our check. svg, I'm going to copy our path here, and I'm going to replace Our path tag, and then I want to remove the unnecessary attributes. So now I can give that a save.
[00:11:47] And if I come back to our icon component, now instead of referencing our calendar, I could reference our check. Now if I hit refresh, you should see our checked icon.
[00:11:58] So I'm going to go back over to VS Code. If you feel like you have the hang of it, now might be a good time to hit pause. Try it yourself. Otherwise, let's keep going. So here within our sprite.
[00:12:07] svg, I'm going to duplicate our symbol again. I'm going to replace check with chevron. And then inside of our chevron. svg file, I'm going to grab our path, and I'm going to replace the path here with our chevron path. And remove these unnecessary attributes and give that a save. And if you want to test it out, you can also come over to your icon.
[00:12:33] tsx file, replace the ID that you're referencing, give that a save, come back over to Storybook. And give that a refresh. Okay, let's go to VS Code, let's do the next one. So I'm going to duplicate my symbol here, paste that in. Then I'm going to replace chevron here with close. And inside of our close SVG, I'm going to grab our path.
[00:12:58] And I'm going to replace that inside of our sprite. svg. I'm going to remove that fill attribute. I'm going to remove these other attributes that we don't need. Give that a save, and if you want to test it, just to make sure, come back over to the browser. There's the close icon. Excellent. Now let's do another one for our eye closed.
[00:13:22] So I'm going to replace our ID here. Now you'll notice that our camel casing doesn't exactly hold up since our title should just be eye space closed. Totally fine. Copy that path. Paste it in. Get rid of our fill and our fill rule and clip rule. Give that a save. And then we can check this as well, just to make sure that everything is working.
[00:13:48] Give that a refresh. Cool, cool, cool. Now back in VS Code, I'm going to go back to my sprite. svg, duplicate our symbol again, then replaceye cIClosed with Opened. And I want to grab the path here. We'll replace that within our sprite, and get rid of our fill, and get rid of these extra properties that we do not need.
[00:14:16] Now let's test this out. So instead of eye closed, we'll say eye opened, and check this out with an arc, looks good. Back in VS Code, let's do our logout. So I'm going to duplicate my symbol again, replace eye opened with logout, replace the title here with logout. I'm going to grab my SVG path and replace that.
[00:14:42] Get rid of the fill and get rid of our fill rule and clip rule. Give that a save. And let's test out our icon. Come back over to the browser. Hit refresh. Good, good. There's our logout icon. And we have our SVG sprite. I'm going to duplicate my symbol once again. Let's make this minus. Then I'm going to replace our path here. And I want to get rid of my Fill attribute that we don't need, as well as the fill rule and clip rule. See, this is starting to get a little bit mundane.
[00:15:18] That is totally fine. I'm gonna do our plus. Let's grab our path here. Place our path. And actually, I'm going to hold off. I'm going to show you a few command tricks that will make this move a little bit faster.
[00:15:36] So for here with plus, let's make this question and grab our path, replace this. Let's come on down. I'm going to create a new symbol and this one is going to be for our thumbs down.
[00:15:55] Make sure there's a space there. Replace our path and then we need one for our thumbs up. Grab our path. Come down here. Replace our path. Perfect. Duplicate our symbol. We've got two more. We have one for Upload, so we need to swap out our title here. Grab the path, and you'll notice that there's three paths here, so we want to grab all of our paths.
[00:16:24] I'm going to replace our path there and make sure that our indentation is lining up correctly. Then I'm going to go ahead and grab another symbol, and this will be our user. Perfect. Let's go ahead and copy that path and paste that in. So now that I've injected all of my icons, let's go ahead and get rid of those extra attributes that we don't need. So I can go ahead and select fill equals white, and I'm going to hit command shift P to pull up my command palette, and I can say select all occurrences of find match.
[00:17:02] And what this will do is it will actually highlight All of my fill equals white, and I can just delete it all in one go. Now I want to do the exact same thing here. With my fill rule and my clip rule, so I'm going to hit Command Shift P again, select all the occurrences and hit delete. Now I can save this and I can test this within my icon component.
[00:17:25] So for example, let's try our upload. Give that a save and come back over to the browser and give this a refresh. There's our upload icon. Now, this is all great, and you could leave it at that.
[00:17:35] But let's make this a little bit more dynamic and a little bit more interesting. So we're going to start to kind of edge into React. If this is new territory for you, just bear with me. So one of the things with React, because we're using JavaScript, is that we can pass in a couple of props. These are just values that we want to make dynamic.
[00:17:54] So for example, I can make the size dynamic. And size is just a variable name that I made up. It could be bananas. It really doesn't matter. Other than the fact that it needs to make sense for you and any other developers that are coming to the project after you.
[00:18:08] So now I can replace our 24 here. And hit command D to select the next instance of that. I can replace that with curly bracket size. So now I can pass in the size to this icon and it could be 24 pixels, it could be 32 pixels, it could be 64 pixels, it really doesn't matter, I now have control over the size of this icon.
[00:18:31] Now if I want to set the default value to 24, I can just simply say equals 24. So I don't necessarily have to pass in a size, if I don't, it's going to be 24. If I do, I can make it whatever I want. The other thing that I want to be dynamic, is this ID that we've been changing. So instead of saying upload here, let's change this to curly brackets ID.
[00:18:54] So this doesn't exactly work as it did with our size value that we passed in because it views our curly bracket ID and As curly brackets ID, it doesn't see it as a JavaScript value. And so in order to tell the code that this is JavaScript, we need to wrap it in curly brackets.
[00:19:13] Now it's still seeing this as a string, just a plain value. And so in order to get it to evaluate that, let's change our double quotes to backticks, and then we need to put a dollar sign in front of our curly brackets. So now it sees this part as a string and then says, Hey, here's a variable that we're passing in.
[00:19:34] Go ahead and evaluate that. Now it says that it can't find ID and that's because we need to pass it in so that it knows that an ID is being passed in. to this particular string.
[00:19:46] So now I'm going to give this a save and I'm going to come back over to storybook and now nothing is showing up.
[00:19:53] Well, if we come down here, we now have controls. That storybook automatically picked up on, and so we could set what the ID is. So we could say that this is going to be upload. And the size here is going to be, let's make it big, 68. So check that out. We change the size. And the ID by simply changing the variables that we are passing in.
[00:20:16] We could also say thumbs up. And now we see our thumbs up icon. Pretty cool. Now, let's take this one step further. Back in VS Code, if I scroll on down to the code that Redwood generated for us, we do have this storybook file.
[00:20:32] There's some information here within the comment block that you might find helpful that outlines what a story should look like and that's actually down here on line 25. But let's kind of walk this through line by line. This is new syntax for you. So all we're doing here is we're importing some content.
[00:20:48] There's nothing you really need to do with that. Totally fine. The next line we're importing our icon. So you'll notice this is just coming from the icon. tsx file that we already created. Then we're going to set up some metadata. We're just telling Storybook that hey, we're using the icon component. And then we export that out so that Storybook can use it.
[00:21:07] Cool. Again, nothing that you really need to do. Type story is just for TypeScript. If your project is not using TypeScript, you probably don't have this line. Then on line 25 is where we're exporting our story out. And so what we can do is we can pass it an args object. where we say these are the values that I want to pass in.
[00:21:28] So for example, I can say here that I want to pass in an ID of calendar and I could set the size to 24 or I can remove that and leave that as the default. So now if I come back over to the browser, I'm going to hit refresh, you'll notice that this defaults to our calendar. Now it's using 68 because we passed in 68 here.
[00:21:46] Our story here is called primary. If we go back over to VS Code, I'm going to swap this out so that we're calling our story calendar.
[00:21:54] If I hit refresh, It's saying, hey, I couldn't find what you were looking for. And that's because each story within Storybook has a unique URL. So it's still looking for our primary story that no longer exists. But if I expand icon here, you'll see here's our calendar and it is loading. So I'm going to come back over to VS Code.
[00:22:12] And I want to create a story for each of our icons. So, if I come back up here, I'm going to make sure I can see my icon list. I'm going to create one for check. Gonna create another one for our Chevron. I'm going to create another one for our close icon and another for our eye closed and another for our eye opened.
[00:22:40] And we want another one for our. Logout. Another one for our minus. Another one for our plus. aNother one for our question. Another one for our thumbs down. We want another one for our thumbs up. And another one for our upload. And last but not least, we want one for our user. So if I give this a save and now I come back over to the browser, you'll see all of the stories that we just created and we can click through to make sure that all of those icons are showing up the way that we would want them to.
[00:23:25] Now this is pretty cool. We have to click through everything. But Storybook also has another feature where if we come up here to the top where we said, hey, we're using our component, the icon component, and here where we're giving Storybook our metadata and saying that we're using the icon component, I can also tell it that, hey, I want to use my autodocs. So now, by just adding this one line of code, if we come back to the browser, You'll notice that I now have this docs link at the top and it's documented our icon for us.
[00:23:58] So it automatically picked up on the properties that we're passing in. It knows that size is a number, which is pretty cool. You can set the number, but then we also have all of our icons listed in a single view. You can also click on this show code button, and it will show you the code that you need in order to use this particular icon.
[00:24:19] Pretty cool that that's all done. automatically for you.
[00:24:22] Awesome. That's going to wrap up our challenge for today. I look forward to seeing you tomorrow.