Innovate with React
- Introductionless than a minute
- Learn the fundamentals of a Component System1 minute
- Setting up the development environment35 minutes
- Importing fonts6 minutes
- Choosing a base React Component Library16 minutes
- Setting up a centralized theme24 minutes
- Injecting icons to our components1 minute
- Writing our first components19 minutes
- Writing custom styles to inject to our components14 minutes
- Adding a more complex component5 minutes
- Making components responsive5 minutes
- Adding hooks4 minutes
- Adding dark mode10 minutes
- Deploying your Component System4 minutes
- Exporting your Component System to a design tool7 minutes
- Prototyping with your production components4 minutes
From Author:
In this workshop, you will learn how to create a Custom Component System from scratch in React, and take it to the next level.
You will learn best practices when building a Component System, as well as the tools that you can use to be a more effective collaborator with other cross-functional teams.
What's included
1. Introduction
2. Learn the fundamentals of a Component System
3. Setting up the development environment
4. Importing fonts
5. Choosing a base React Component Library
6. Writing our first components
7. Setting up a centralized theme
8. Writing custom styles to inject to our components
9. Injecting icons to our components
10. Adding hooks
11. Making components responsive
12. Adding dark mode
13. Deploying your Component System
14. Exporting your Component System to a design tool
15. Prototyping with your production components
This workshop has been presented at React Day Berlin 2022, check out the latest edition of this React Conference.
FAQ
Anima is a prototyping tool that allows designers to convert design assets into code. It facilitates the creation of prototypes that resemble the final product by enabling the embedding of functional components directly from development environments like Storybook into design tools like Figma.
The integration allows for direct synchronization of component libraries from Storybook to Figma. This enables designers to use actual production components for high-fidelity prototyping, ensuring consistency between the designed prototype and the final product, and accelerating the design-to-development workflow.
The 'dark mode' feature in Storybook allows users to switch between light and dark visual themes for UI components. It is implemented by defining separate themes for 'light' and 'dark' modes in the Storybook configuration, which can be toggled by a user interface control within Storybook.
To deploy a Storybook instance to the web, you can build a static version of your Storybook using the build command and then deploy this static site to a hosting service like Netlify. This process involves generating a static output directory and then dragging and dropping this directory into Netlify's deployment interface.
Using responsive font sizes in Storybook helps ensure that typography adjusts appropriately across different screen sizes, enhancing the readability and accessibility of UI components on various devices. It's implemented using the 'responsive font sizes' utility which automatically adjusts font sizes based on the screen width.
Video Transcription
1. Introduction and Table of Contents
Hello, everyone. My name is Cristobal Chao. I live in New York City, but you can probably notice an accent. I am from Spain originally. I came to the States 10 years ago. I live in San Francisco and now I live in New York, so closer and closer to Europe little by little. Let's just start. So here, probably you are already you have in front of you. The, the Table of Contents what I'm sharing with you right now. So what we can do is we have two types of navigation at this level.
Hello, everyone. My name is Cristobal Chao. I live in New York City, but you can probably notice an accent. I am from Spain originally. I came to the States 10 years ago. I live in San Francisco and now I live in New York, so closer and closer to Europe little by little.
Let's just start. So here, probably you are already you have in front of you. The, the Table of Contents what I'm sharing with you right now. So what we can do is we have two types of navigation at this level. One is you can click on any of these sections and then it will get you there, or you can click here on the top right corner in next to go to the next session. All right. We will be covering the introduction, just a little bit of intro. Then we will be doing the setting up the Dev environment, and we will have three sections of implementations where we will cover the very basics of implementing a design system in React. And then we will be adding more and more complexity to it. All right, at the very end, on level up, that's the part that we will be covering at the very, very end. But in any case is, the, I think is the most exciting part. Anyways, let's jump straight in. I know that there is a comment. All right, let me double check. Yep. And all right, it's time to go, guys.
2. Introduction and Environment Setup
Introduction: A component system is a single source of truth that communicates the values, tone of voice, and guidelines of an application. It ensures consistency and cohesiveness, benefiting both users and developers. Next, we will set up the environment by installing the necessary packages and creating a new React app. I will guide you through the process, but please note that I may not be able to address all questions. After installing the app, we will open our IDE, clean up unnecessary files and dependencies, and ensure that the React app is still running.
So the introduction. Well, before I jump into this as well. If you guys get stuck at any given point, every single section except the introduction has the downloaded file at the very end. So imagine that you are on, not in this section, on the next one, on setting up the environment, and you get stuck somewhere here. You can always get the latest from this section at the very end. You have the link down here. All right. I know that you may get stuck. So you can always get back on track, all right.
Anyways, so introduction, guys. So what is a component system? So a lot of people have different opinions about what a component system is. But at the end of the day, it is a single source of truth, right? You have all the elements that are used across your application that pretty much communicates the values of your application, the tone of voice, the guidelines, right, the patterns. And it's not a finished product, right? Like we think sometimes that a component system is just the final product, but no, it's not. It's at the end of the day what the product is going to look like so things are more consistent, all right. Do you want to have a component system if you want to see if you want to get an app that is consistent and cohesive? So I think if you have a small company, you probably are not thinking about this. But at the end of the day, this will hurt you. And it will hurt you two ways. One way is from a user level, people will get confused like, where am I? And from a developer perspective, you are not efficiently getting the most out of it, because once you have a component system, you can reuse stuff. And people know what is the latest and greatest. So it's a greatest source of communication.
All right. We're going to jump into setting up the environment. Now, I have to say. I will be doing this with you. So we will be installing everything from scratch. I'm going to have this side by side by side. And if you guys again, if you guys have any questions, let me know. But I'm not going to be able to address all of them. All right. So I have my terminal on the right side. I have on the left side where you should be as well. And we will be installing the packages first. You can go one by one if you don't have NPX or if you don't have yarn. I will be using yarn. All right. But if you have it, if you have if you use NPM is fine. Just understand that any time that you see a command in yarn, you will need to translate that into NPM. All right. I think it's pretty straightforward. But in any case, we're going to do a create a new React app. I expect that all of you know what this is. There are links to the docs here, but I also have the snippet right there. Just copy this and paste it. If you don't have NPM, you need to install it on this first command right here. All right. I'm going to zoom this a little bit. Just in case if you don't see it well. Another thing while I'm installing this, I will be doing this in Visual Code. I think you can use any ID you want, but you may run into some issues with some of this stuff that I will be explaining. But we will cover that in a second. But the thing is, if you have Visual Studio, great. If you don't, best of luck. All right. I hope you will be able to get anywhere. But just in case, I'm just telling you this. We are installing a new React app from the very beginning. I'm doing this with yarn. If you have Visual Studio, you're going to start starting that now because we will get there in a second. All right. I don't see any questions. I hope you guys are not shy. All right. Cool. So we install our React app, and now we can just go to the next level, which is going to our new folder, and start in the server. I do yarn start. Again, if you're using npm, it will be npm run start. All right. We're getting new people coming. All right. Cool. So I just ran the app. I see it here. You probably are familiar with this. You have seen that before, I expect. Anyways, I'm going to come back to our presentation, our workshop, and the first thing we're going to do is we're going to open our IDE. In this case, I will be using Visual Studio, as I mentioned. And we're going to do some cleaning. All right? There are some files that we don't need. One of them is report vitals, and the other one are tests. All right? Tests are very important, guys. Don't get me wrong, but for this presentation, for this workshop, we don't need them. So I'm going to be removing those so things are a little bit cleaner, all right? So I'm going to be removing these files. Report web vitals, setup tests. All gone. If I go now to index JS, I will need to remove some of these files and some of these instances because we don't want them to be around, all right? On the package JSON, you can also remove some of the stuff that we don't need, like some of these dependencies on the top, we don't need them. But because we already install it, I mean, it's fine. Same with the web vitals, we can just remove that, all right? Cool, I'm going to zoom this a little bit so you can also see that, all right, fantastic. And I'm going to double-check that that React app is still running.
3. Installing Storybook and Exploring its Features
We cleaned our app with the necessary dependencies and installed Storybook. Storybook allows you to have all the documentation you need for your single source of truth. It provides an overview of component capabilities, including different states and controls. You can also see the component's documentation, copy code snippets, and view other stories. Additionally, Storybook offers tools for responsiveness, guidelines, and more. You can organize components in the left navigation and define archetypes for controls. We also have access to other components like the header and page. To clean up, we will create a new folder called components and move our reusable components there.
Same with the web vitals, we can just remove that, all right? Cool, I'm going to zoom this a little bit so you can also see that, all right, fantastic. And I'm going to double-check that that React app is still running. All right, great. So we cleaned our app with the necessary dependencies. Next thing is installing a storybook. So you have this snippet right there and you can use it on your terminal. All right. So I expect that you guys are right now with me. And if you get stuck, again, you can always follow me at the very end, you have the link to download the code. You will need to install the dependencies and run it but you can always get back on track, all right? So we are installing a storybook. By the way, now we're going to run this storybook instance. And I just want to say that we're going to have two different servers running. One of them is a storybook, another one is our app. The main reason why I want to show you the two of them is to showcase the reusable components that we will be creating. At the end of the day, storybook will be used as our library and the app is to showcase that we can reuse these components elsewhere. So I recommend you to have these two tabs on your terminal or however you do it open and you may need a third one if you want to do anything else. So I have this tab right here. I'm gonna call it Storybook and this other tab right here, I'm gonna call it app. So for me, I can see that I know where I am, okay? Okay, we've got more people coming. Now, things are happening because we're installing some instances, I believe. So what I'm gonna do, I'm gonna restart the app server and now our Storybook has been installed. And what I can do is type jarn Storybook. So I run this second server and usually this is going to be running on 6006, all right? If you have something in 6006, it will ask you and you will probably need to answer yes and you will get it in the next port which is 6007, all right. So a Storybook is starting and we have it right here on the left side, you can see it. So I'm going to show you just a little bit about what the Storybook is, if you haven't seen it before. So Storybook allows you to have all the documentation you have for, you need for your single source of truth. This page right here is actually, you can find it under SRC stories and Introduction Stories. I'd recommend you to install an extension to actually see the MDX properly because this is terrible, but in any case, everything that is here is been running here on the left side. Like if I change this Welcome to Storybook to Welcome to Innovate with React. I should see that in real time on the left side. All right, we're not gonna touch this file anymore. I'm gonna close it. But I'm gonna show you also like some of these components that came for free by just installing a storybook. So this is the first component that we have, which is a button. And there are different states of this button that you can see on the left side to showcase like overview of its capabilities. You can also have these controls, which are down here, and you can toggle them on and off. So the primary is a primary prop and you can see how it behaves when it's false and when it's true. You can also change the label to whatever you want, then with react, for example. You can change the background color of the components. And then the size right here. There are some actions that I believe if you click on them, you can also see them, and interactions, to be honest. I still want to figure out what that is. I haven't used that. Then docs, which is pretty exciting. We have the docs for free. And that allow us to, when we are even changing the state of our component, we can get the code at every state. We can copy it and we can paste it elsewhere. Pretty simple. So you can come here, change the state a little bit, and copy the component, and paste it to your IDE. You can also see other stories. And there are also more exciting stuff here. There's controls. You can zoom in and out, if you just want to make sure that things are working fine. You can have also the dark backgrounds or light backgrounds. You also have the capabilities to see how these respond into different screen sizes, small mobile, preset viewport. You can see these guidelines, but if you are a developer, probably you won't get a lot from this because you are used to dev tools, as I am. But this is a single source of truth that is supposed to be also used by people that are not technical. Like if you share this with designers, they can also see the latest and greatest. And for them is pretty friendly to use tools like this, which you can actually get all the different paddings, margins, and all the different guidelines of your component. So you have some tools right here. Some of them are useful. Some of them probably are not that useful. Then the last bit I want to show you is a button.stories, stories.jsx. It's actually the file that is rendering. This one on the left side, right? You look at this, there is on the seven, on line seven, it says example button. That example is how you want to organize. So whatever is on the left side of this lash, that is where this component is going to live in our left navigation. There is this collapsible section, it's called example. If I change this to, let's say library instead of example, we're running into an issue, but as soon as I click elsewhere, then you're going to see like our, our component right there, all right, this under library now. As soon as I change this, it will go wherever I want to. And the reason why you run into an error is because this is storybook instance is changing the URL constantly when I change any state, all right. So if I change this to somewhere else, right, like then on library, I don't have anything else, and now is running into an error, right? Now it's under FF, right? I'm going to get back to library, I'm going to save it, and probably that you'll see working. And this is also, this is happening because we have whole like reloading happening, right. So just be conscious about it. Like if you run into issues, sometimes it's just a matter of changing where you are on a storybook, all right. Then we have here some archetypes, and these archetypes are defining some of the controls that we have right here. You see background control, but we also have the capabilities of adding other other arguments under these different states. So we have primary, right? Anytime that we do a template bind, it's doing a template bind of our component button. And this button is being imported on the top. This button on the top, if you wanna find it, is also, it's called button.jsx and has our component information, right? But if you go to button.jsx, you will have here what is rendering on the story, all right? If I change primary to something else, like let's say workshop, and then I change as well this object right here, name, then it will be called workshop, all right? This is just the beginning of Storybook. If you're not used to it, this is just a sneak peek of what you're gonna get. All right, so we also got other components like the header and the page. These are coming for free. Storybook give us access to them. One thing we have to do is we're gonna clean things a little bit, all right? And the first thing first is this is a little bit messy right now. We have stories but everything is inside the stories and it doesn't make sense. You know, stories are supposed to be just for a storybook but our components should be reusable. We want to reuse them elsewhere. So it doesn't make sense that we have our components inside the stories. So what we can do is we're gonna create a new folder called components inside SRC, all right? And this folder is going to have the different components that we have in stories.
4. Organizing Components and Enabling Absolute Paths
We organize the components by creating separate folders for the button, header, and page. We moved the necessary dependencies, such as CSS, JSX, and stories, into their respective folders. We also made sure to export the components as default and updated the imports accordingly. Additionally, we enabled absolute paths for easier import management. This involved creating a js.config.json file and setting the base to SRC. Now, instead of using relative paths, we can use absolute paths to import components and other files. Lastly, we created an index.js file in each component folder to index the files. This allows for cleaner and more organized code.
All right, so we're gonna move there, R button, the CSS of R button and everything is going to crash now, all right? Because we're moving things around. We even are going to move the storage.jsx there and I'm gonna go there in a second, all right? I'm gonna move the header. I'm gonna be moving everything and because I'm using Mac I'm gonna do it even faster, all right? So I'm gonna move the header and the pages. Wait. I'm gonna copy this, paste it right there and I'm going to remove them for some reason. My CAD doesn't work, so I have to remove after copying. This is terrible. Anyways, components.
So in components we have everything there, right? And what we want at this point is to organize things a little bit. So we're gonna create a new folder called button and we're gonna move like all the button dependencies under there, the CSS, the JSX, and the stories. Same thing is the header, everything is crashing because we're moving things around. With the header, we're going to do the same and with the page we're going to do exactly the same. All right? So we're moving things on their own folders and everything is crashing because we have to still make a few configurations. So now everything is under button, header, page and the components. Everything is way more organized. So now we'll go to button. I'm gonna close this. And then you're going to see that our button stories, JSX is actually importing our button but is not importing our button by default which is pretty strange why the storybook team did it that way. Under button, there is only a button. And usually when you have a reusable component, you want to export that as default. So how do we export this as default? I bet you know how to do it, but we're gonna do pretty much is removing this export and then we can export it on the end. You can also do it up there, wherever you want. I'm used to using this way of doing things. So I'm gonna export by default, the button and then under stories, I'm just gonna remove this curly braces because now I'm importing them on a new default way. This component right here is already there and I'm gonna double check if it's working. Maybe there is something else that we are missing. The header is complaining. So the header, same thing as we did with the button. So the header is importing our button. We're gonna remove those curly braces because now we're importing this on a default way. And same with the header, we're going to export this as default, all right. And in a second, we're going to do exactly the same for our page. If you go to a header stories, you will also see that we need to change, we need to remove those curly braces, all right. And because we have this and that example, let's rename that to library. All right. And then if I see here, this is still complaining. It says, oh, if you look at the header, it's not dot slash storybook, all right. It should be dot dot button, right. Our button is now elsewhere. But here's the thing, right? Our button now lives under button JSX. So in order to import this, we need to do this terrible thing, which is a button slash button. Page is complaining. Let's go there. Let's fix what the page is saying here. So same, we're importing this by default, we're finding the header. And in order to find header, we're gonna clean things up, guys. Don't worry, this is terrible. But you're going to see, we're gonna do that in a second. All right, so now things are rendering. Our page is not complaining, but we also need to remove this, making sure that everything is importing from a default perspective. And the title should be library, as we did before with the button and the header. And now everything is looking fine. The page, something is happening with the page. Let's double check. Oh yeah, so our page needs to be exported by default. We're just cleaning this a little bit. I wonder why other study people have it this way. Anyways, so we have the page now. Everything now is way cleaner, but it's not as clean as we want. This is a very, I don't know, like this pattern right here is terrible, guys. We're gonna do two things, all right. Ideally, we're going to use absolute paths, right. And I have that as part of the documentation. As you see on the storybook cleanup. We move the components from stories to components. And the second thing is we're gonna enable absolute paths. I see this technique pretty, pretty useful because it simplifies your imports quite a lot. And as soon as you have this well-configured that you can do it at the very beginning of your project, then it make life way, way simpler. If you start building your application without these foundations, it's super easy to get like super messy code elsewhere and things start dragging everyone. So, I believe if you said this earlier in the project, it's gonna make you happier and all your developers. Anyways, so, so there is a new folder that we didn't talk about which is called dot storybook, and it's on the route, right? That folder right here has two different files. And those are like the files that help us actually import all the stories. Those are like part of the build system when we run the server, all right? What we're gonna do now is you can actually copy and paste the whole thing and replace the whole file. All right? But what I want you to see is the last bit because this is pretty much what we added, all right? This last bit right here that says Webpack final allow us to have aliases. And aliases are going to enable these absolute paths or capabilities for a Storybook, all right? And as I mentioned, we have a Storybook as one server and we have our app in our other server, right? We have a Storybook and we have our app. This only influences a Storybook, right? So if we want to have also absolute paths in our app and this is the part I wanted to mention before, we are gonna create a new file called js.config.js, all right? You may know about this file. It has like basic configuration for your IDE and I have this in point number four. I'm gonna do that right now with you. I know that I'm going back and forth but it's better to do it once so we know what's going on. So we're adding, sorry, js.config.json, all right? No js, json, apologies about that. And what we're doing here is we're setting the base to SRC, right, and what we get is all the capabilities we need for absolute paths for our app. This works in Visual Studio. I don't know if every IDE allows you to have this. So if you get stuck because this is not working for you, you may just want to stick with relative paths, okay? In any case, now that we have our app set up with enabling absolute paths as well as our storybook, we can go to our header, for example, and instead of importing this way, we can do this, component slash button, right? If we want to import anything else, like let's say we have a folder called utils or constants and their source, we will say constant slash the name of the file instead of finding them, right? Which sometimes is very cumbersome because you may have like different like levels of different hierarchy between like different files and different folders. It gets pretty, pretty messy. So we do this, it's way simpler, right? Anyways, now it's probably going to be breaking because the last bit that we need is to create a new file under any of these components called index.js. And this index.js is gonna index our file. And you can grab this snippet right here on point two. And then you need to change this name of component. In this case, it will be bottom, right? So this is indexing our bottom, all right? Some people prefer to have, on the index.js, the logic of the bottom.
5. Indexing Components and Restarting the Server
I don't like that. If you have multiple components with similar names, finding the right file becomes difficult. By indexing the components, the process becomes simpler. Restarting the server after making changes is necessary. The button is now working, and the process becomes automated with practice.
I actually don't like that. And the reason being is once your product gets larger and larger, if you are using Visual Studio, for example, you are going to find that, if you want to find any files, let's say, like you want to find a bottom, the index, the primary search is gonna be showing up right here. So think about it, If you have like a component called bottom another component called bottom-icon, you can have another component called bottom-group, right? You're gonna get all this index.js showing there, and you have to keep a closer look and try to find the path. This way, if I just find bottom and I see it right there, and I go there, right? So it's way simpler. And this way, I'm just indexing the bottom.
So right now on the header, right, I can just import it this way, which is way simpler. If you look now, our bottom, CanResolveComponentsButton, all right. So if this happens, you have to restart your storybook instance. And I forgot to tell you, but anytime that you change files under dot storybook, you want to restart your server, all right? You need to rebuild your app. So I'm restarting the server. And we will be seeing that, hopefully, working. All right, here you go. So here it is, the button is right there. It's working, the different states are there. Um... And this is way simpler, guys. Let me tell you, this pattern may look, oh my god, this is so many steps. Once you do it two or three times, it's super automated. And you can do it in seconds.
6. Organizing Components and Improving Accessibility
We organize the components by creating separate folders for the button, header, and page. We moved the necessary dependencies, such as CSS, JSX, and stories, into their respective folders. We also made sure to export the components as default and updated the imports accordingly. Additionally, we enabled absolute paths for easier import management. This involved creating a js.config.json file and setting the base to SRC. Now, instead of using relative paths, we can use absolute paths to import components and other files. Lastly, we created an index.js file in each component folder to index the files. This allows for cleaner and more organized code. We installed the accessibility add-on for Storybook, which helps identify accessibility issues in our components. By using the add-on, we discovered that the button component had insufficient color contrast, making it inaccessible. We made the necessary changes to improve the color contrast and ensure accessibility. We then imported the button component into our app and verified that it was working correctly. We also explored the accessibility features of the add-on, which provide valuable insights into the accessibility of our components from different user perspectives. Finally, we addressed an issue with importing fonts in Storybook and the app, ensuring that the correct font was being rendered.
So now we're gonna go to header, and we're gonna do exactly the same. Another index JS file. We're gonna index our components, and we're gonna do exactly the same. I usually copy my index JS from button and paste it to the new one. And then change the name of the component. All right? And same we're gonna do with the page. So another, we're gonna do like another file on their page called index JS. Paste it and change our default. All right. Now, if we look at our header, it's working. But I think our page, oh, our page is working too. Let me double check our page. Yeah, but our page is importing our header in a very, very ugly way. So we're gonna just do now that we have absolute paths, components slash header, and that should be working. All right, it's working. And our header looks fine and our button looks fine too. All right, so we clean everything up. Now we have absolute paths and we're ready to go. Now, one thing I have to mention is this button right here, you may find that is fine, right? But let me tell you one thing, is not accessible, all right? I found this recently, and we have an add-on that we can use to see what's going on here, all right? So add-ons under storybook, you can find them on the website and you can actually get the snippet here. We're using yarn, if you're using MPM, you can just copy this and paste it. We're going to install this accessibility add-on, I think it's very, very useful. So we're going to install that, so adding a new tab, we're gonna just copy and paste that snippet, and this will be installed pretty soon. All right. In the meantime, while it's installing, we can also add this new add-on under main.js, all right? You don't need to copy everything, just make sure you get the storybook slash add-on, A11Y, which stands for Accessibility, all right? So in main.js under.storybook, you're going to see a new, like there is an array that is called addons. Every single addon, you want to add it right here, all right? So in this case, we're going to create a new line, and paste this storybook slash addon accessibility. Since we change our main.js in Storybook, we need to restart our server, all right? But let's wait until the add-on is installed. All right, it seems it's installed. I am going to restart the server. I'm gonna restart the server, and we're gonna see something pretty cool in a second. I am restarting the server. All right. Right here you go. So, I don't know if you noticed something different, but there is a new icon on the app bar. This one right here. If you click on it, you can see how the component behaves with those different conditions, all right? This way, it helps you to actually understand what's going on from different user perspectives, right? There is another tab also called here, accessibility on your controls. By the way, these controls, you can have them down here or you can set it up on the right side by using this control right here. Since I have my screen side-by-side with my terminal, I prefer to have it down there. But you can also have it here. For the sake of having that here, I'm gonna keep it here. So there is this new tab called accessibility. If you click on it, this is the most useful part of this add-on, you're gonna find any issues right away. And as you can tell here, this is a violation. It's telling that elements must have sufficient color contrast. So that's why this component is not accessible, right? So we have to do, right? Is change our background color or change the text color, right? If we change our text color, if you go to button.css and change this to color, let's say black, sorry, black. Sorry, I'm using JSX. JSX, this is CSS, alright. Sometimes I'm having a hard time. Wait. Oh, it's okay. It's a storybook button primary, alright? Dark color, white, we're going to change it to black. And is this, okay. If you go back and forth with accessibility, now it says side zero violations for passes. Zero incomplete, look. This button now is accessible, but it's ugly. It's pretty ugly, right? We're going to fix that in a second, but yeah, this button right now is accessible now, but again, is not accessible. Well, it's accessible, but it's not beautiful, right? That's what I wanted to say. But anyways, with this button right here, we can also change that. Instead of being text black, we can also change the background color, the blue, to be a little bit darker, so it's accessible, right? But in any case, we're going to keep it this way for now. We're going to fix it in a second. I'm just showing you the accessibility capabilities right here, which I think are pretty useful because you can get this information right away for any single component that you have under Storybook. All right, it's pretty useful stuff. All right, now, coming back to where we are. So we change the primary color contrast because it's not enough. And then we copy and paste it to our app, and well, our app now doesn't have the button. So what about if we add the button right there? All right? So instead of this link, we can just import, well, first, we will need to import our button. And since we have right now absolute paths, it's way simpler to import those, right? Because we know that button is under components. So it's import button from components slash button. It's that simple. All right? So button, button right here. And let's see what's happening right there. Okay, we restarted the storybook, but we didn't restart our React server. So we need to restart the React server too, and hopefully this is going to work. All right? When we add a new JS config, this, we need to actually do the same thing. We are not seeing any button. Oh my God, what's happening here, guys? So when this happens to you, and this is why a storybook is pretty useful. You can always go to the docs, get the code from your components, copy that, right? And paste it, in this case, in our app JS. All right, so instead of me guessing what I need to do, I can just copy the state of this component at this level and see it, right? Look, it's as simple as that. Instead of button, we can say learnReact as it was before, and that's it. So we completed our first section of the workshop, again, if you guys got stuck, you can download right now and install it. You will be at this level, all right? Now, we're gonna go next. So we're gonna press on the next button on the top right corner, and we're gonna get into things that are more interesting. All right, importing fonts. All right, one thing that I want to mention is this button right here. And again, this is also something that I am, I am surprised to see it, because this button right here, if you look at the CSS, is supposed to be important in Unito Sans, right? But, if you take a closer look and open our dev tools, and I imagine you know how to open dev tools, right click, inspect. If you open the computer tab under elements and scroll down, you're going to see that Helvetica new is being rendered, which is our second option in our font. So Unito is not being imported. And same thing with the app. So, we have to fix it, right? We have to fix it because for some reason, the Storybook team didn't add that. Maybe they knew that we were doing a workshop So, we need to make things easier for everyone. And this way, everyone can learn how to import fonts.
7. Importing Fonts and Setting up Storybook
To import the desired font, we can go to Google Fonts and select the font we want. After adding the font to our shopping cart, we can copy the provided snippet and paste it into a new file called preview-head.html under the dot storybook folder. This file is responsible for injecting the font into the storybook iFrame. We also need to copy the snippet and add it to the public folder under Index HTML to ensure the font is imported into our app. With the fonts imported, we are ready to proceed.
So, how can we import this? So, what we can do is we can go to Google fonts. I don't know if you know about this website. Just pretty cool and you can find fonts here that are mostly free. I think all of them are free, but anyways. I searched by the new Unito sans, I can click on it I can click on it and this is a new version of Google fonts, which is pretty interesting because I believe the previous version for me was way more straightforward. But anyways, so Unito sans is right here and what we're gonna do. And I don't know if you are familiar with Google fonts but the concept here is like, you are like an e-commerce platform, but everything is free, right? So we can select our fonts and send them to our shopping cart, right? In this case, we only need the regular 400 so we can click on that button. We need the, I believe is the 700 and the 900, right? So the 700 and the 900. If this right navigation doesn't show up is under this button on the top right corner, all right? And you can see on the review, this is our shopping cart with our fonts and is free as you may imagine. So here we can just copy this section. And what we have to do is we need to paste this in a new file under dot storybook. This file under dot storybook is called preview dot Head dot HTML, all right? And we can paste it there. You can also find this on the documentation. Everything that I'm explaining you here is on the doc. As you can see here, we will import as part of preview-head.html. So what is this file? What is this file that we are adding here? Since we created a new file under the storybook, we need to restart the server. And I may start restarting the server so you can see what is going on. But what is this file preview-head.html? So this canvas in a storybook is an iFrame, all right? So anytime that we are switching between the different buttons, the different components, this is being rendered in different iFrames, all right? That's how a storybook works. So preview-head.html is anything that we wanna inject on the head of our iFrame, all right? So what we imported from Google Fonts and pasted there now is it should live under head, somewhere here. Look, I'm seeing it right there, all right? And I don't know if you notice it, I'm gonna zoom in a little bit, but this bottom now, the label has changed and we can double-check that now it's NuNITO, all right? Now the font is being rendered, finally. Fantastic. However, if you look at your app, this is not being rendered and you can double-check by checking in DevTools, it's importing Helvetica new, and that's not what we want. So as I mentioned, Storybook is one server, our app is another server, all right? So we need to copy this snippet, right? And we're gonna move it under public folder under Index HTML. You can paste that under the logo if you want to. And now you can see that we have our new font, right there. All right? Fantastic. So we have already our fonts imported in both places, ready to go, great.
8. Choosing and Installing Material UI Library
When choosing a React component library, you get high quality components that can be customized to your own component system. Material UI is a popular choice with a large community and excellent documentation. Installing the library is straightforward, and you can easily import components like the button. The button component has different variants that can be customized using props. By using the Material UI library, you can create interactive and visually appealing buttons with ease.
So now, as I mentioned, do not forget to also import that as part of the app if you wanna see it with a better font, with the supposed font, anyways. Choosing a React component library, next section right here. So why are we choosing a React component library? Right? Well, you may think that this is, that you prefer always building your own components while using something else, it's gonna add a lot of size to my bundle. I prefer to keep things simple. That's fine. But the thing is, when you choose a React component library, you're actually, I mean, you're getting a lot of things for free, right? You're getting things like high quality components. If you look at our component right now on a storybook, this doesn't have any single interaction. Like you hover, I just see the pointer, but nothing else. I'm clicking on it. Nothing happens, right? I mean, it's fine this button, but it's not really responsive. So this is usually where you start, right? But when you have like a component library, you're gonna start reusing things from zero and there are already high quality components that you can customize as you want, right? And make it custom to your own component system with your own color scheme, with your own typography. So you're building that, right? You're creating your own brand, right? The thing is you also have a team working for you, you know, like you have, like, for example, we're going to be using material UI and I'm gonna go there in a second, but the material UI team is a fantastic team. These guys are amazing. When I was part of Google, we try to also do the same. We try to create a react version of our component library. We ended up saying pointing to material UI because they were doing a better job than us. I shouldn't say that, but I have to say that too because the community around material UI is so large and the development team there, they are constantly making updates, making sure that everything is bug free and you get accessibility, you get extensibility, you get a lot of things for free. So it's like, if you have your own one-person company, by using a component library, this is like having a team that is working for you, which is amazing. Right? Anyways, we're gonna choose material UI, as I mentioned. The reason being, if you click on this link, you can also find the communities that from this article, this is recent from this year, and the comparison with other libraries, there is Ant, there is Chakra, Bootstrap, those are like all great. But I think material UI by far has the highest community. Right, and when you have a very high community, you usually think of also having the right documentation. If you get stuck, you also know that this is being a maintain by a team of people, day by day. Right? And this says origin, Google, well, I would say it's back up by Google, but it's not made from Googlers. All right, that's FYI. All right, anyways, material UI. I don't know if you know about them UI. It's pretty cool. If you go to the website, you have the docs. You can search by components. For example, if we look at the button, you can get here, find the buttons. You can get the documentation of different states right here, all in React. This component by default, I already used material design. And you have right here so many different components, like check boxes, radios, selects. There is a lot of things going on that you get for free, all right? So this is pretty exciting. And anyways, we're gonna jump to installing the library, all right? So here we have a link to install the library and you also have the snippet, all right? So you can just copy and paste the snippet on your new tab on your terminal and we're gonna be installing Material UI right now. Right, all right, it's gonna take a little bit. I don't think it takes a lot. Look at that, how fast that was. All right, we install MUI and we're gonna do some cleanup, all right? So first things first, so our button component looks as I mentioned, looks terrible, doesn't have any interactions. Look at that, this is so bad. Anyways, we're gonna go to our button.jsx and I'm gonna import the button. You have the snippet. I know you don't have the snippet but it's pretty simple guys. So what you need to do is, you can do just import button from at MUI Material slash button, all right? As we do with well, we have to, we have to also know that if one important button but our component there is bottom there is a conflict here. So instead of important button we're gonna say MUI button instead, right? And hopefully that's okay, fantastic. So this MUI button I can just replace this button that I have here instead and as soon as I have it, it is running into an error. Why is that? We need to restart Storybook probably because we install a new dependency, right? So we're gonna restart Storybook and hopefully we're gonna see this new bottom right away. And here you go, here is the bottom, right? You may notice that this button already has some interaction. However, if you look at the button documentation by the way, if you got stuck into how to import the button you can also get it from the docs, all right? It's right there. And as you can tell, there are different variants and you also have access to the API on the right panel at the very bottom where you can see, like, if you click on button you have access to all the different props and values. All right, but just to make things easier we're gonna start by making some changes to our button. It is this variant here, all right? That as you can tell, there is text, contain, outline and this is the representation of these three. So if I go here and then change variant to contain, right? Then our button looks way better, right? However, this props right here, right? We need to inject them so they support material UI. All right? So, it's gonna be pretty simple. So first things first, we're gonna add a new property called, we can add it at the very end. Variant and that variant we're gonna add it here, injected to this prop right there and you have not seen anything, right? Why? Because we need to, in.stories, we need to inject that as well, all right? So this primary, what about if we call it contain instead, because contain is the variant. So I'm gonna say that variant contains. And if I do it, this is gonna complain, but as soon as I click on it, I'll see it, all right? And instead of secondary, we can call it outline, which is the second version of the variant and we're gonna add a new prop called variant outline, all right? Same we will do with text. So in large, we can keep large. Large is I think is useful, and it's small. So let's create a new one, a new state, and we can call it text and variant text, right? Done, so we now switch between the three. The text is not showing because, why? Oh, because I forgot to add, I forgot to bind it, okay? Oh, it should be called, sorry, it should be called text, and the arcs. Right now, it's right there, but what is going on with this border right there? I think there are some conflicts happening with our classes, so we're gonna remove the class name right there, and we're gonna remove as well the style. We don't need that. Let's remove that, and now our bot one has three different versions. Outline, contain, and we have it right there. Which is great, it's looking good. Anyways, as you can tell now, our bottom is way more interactive. We have hover, we see the shadow, we can click, everything looks way, way better. If you look at the docs, these descriptions right here, we got the new variant prop, but it is not description. In order to add it, you can just add these on prop types, and you can call it instead variant. And this is a string. And here you can add some documentation. In this case, this is the variant state of our button, whatever. Not great comment, but if I add it there and then I refresh, hopefully, I see, oh yeah, here you go. This is a variant state of our button, and it's a type of string, and I have the control right there. One thing that we would like to do now, our accessibility is passing, which is awesome. And one thing we need to do here is this contain is a string, but it will be very nice if we could do something like this, right? On our controls. But instead we can also add selectors, well, select component instead of having radio buttons for that. So how do we do it? So under our types in our button stories, we can use background color, we can just remove it. We don't need it. And then we will be adding variant, which is the name of our prop. And then we'll do type and this is a select and options, which is the second key. And this is an array of strings and we can set contain, we can set outline and we can set text. As soon as I do it, this component, it was a text field. Now is a selector, right? Now I can just switch between the three different variants on the controls. How cool is that? So cool. Anyways, we have our library right there with our button looking great. The different versions of our button.
9. Adding Colors and Sizes to the Button Component
We added a new color called 'type select' to the button component. The available color options are primary, secondary, success, error, info, and warning. We also included the 'info' and 'warning' colors. Additionally, we added the 'color' prop to the button component and removed the 'mode' prop. After making these changes, we noticed an interesting behavior with the rendering of the button. We reset the changes because we realized that we haven't added our theme yet. We also added the 'size' prop to the button component. Finally, we replaced the previous version of our button component with the code from the Material UI documentation, resulting in a high-quality component.
This is great, guys. There is also things that we can add as well. If you look at the button itself, it also has colors, right? So we can also create a new one called color and is called type select. We're kinda start up in the control first and then we can set the different props. The very first one is a primary, then you're gonna add the secondary and then we also have success and we can have also error, right? There are more. If you wanna see the full list of these types are right here. We have primary, secondary, success, error, info, warning, so we can also add those if we want to. I'm gonna just add it info, warning, fantastic. So we have it there and then this color, I think we don't have it in our props yet. So we're gonna include that, all right? So color actually, it should be coming from this but in this case, just let's add that so we can see what's going on. And then we forgot to add the comma right there, sorry. Color and then this mode right here we can also remove that, we don't need it, fantastic. So our button now, there is something going on. Very, very interesting what's happening here. Color, type, select options, there was something happened right there. Click the render version of our button. What do we do, correct on, right here. Here you go, something happened there. That was interesting. All right, anyways, our color is also being important because we add also the structuring props, right? So that should be there. Anyways, we have this Color, New, Control down here and we can see how it behaves. But we have a problem right there. Okay, yeah, okay. So I set this up guys, but well, I will reset that. I will reset that and the reason being is we don't have our theme yet. I went a little bit ahead. I got very excited. Our color now, let's keep it primary as it is. We will be doing more stuff. But that will be on a section that is coming next. So we added this. Now we go to our section. So we added color, our size. I think our size is not there. Let's double check. Look, it's not there. This is a pretty simple one. So size, we just need to add it as well as part of our props. And now I can just switch between the three, all right? And if we want to as well, you can also add it as part of the archetypes and have a selector. But that's up to you. All right, cool. Fantastic, so now, we did the cleanup. And then finally, our application. It has this new material UI component, but it's not looking how we want. So as we did before, we can go to the docs, get the code from our component, we can copy that. And if we go to our app JS, we can just paste that and replace in our previous version of our button and if we look now, here you go. Here it is, right? Looking way better than before. So now we have a high quality component right there. Right now. Anyways, here, this is the first, the end of the first part. As I mentioned, you can download the code right here and get back on track. All right, and we're gonna go now to the next section.
10. Setting up a Centralized Theme
A centralized theme allows for control over brand elements such as colors and typography. By avoiding hard coding and reusing from a single place, consistency is achieved. Material UI provides a color tool for selecting hues and tonalities. Typography options are also available, with variants like H1 and H2. The theme configuration is injected into the React app using the ThemeProvider component. The color palette can be customized, and changes are immediately visible. The typography can be adjusted, and components like Typography and Box can be used for styling.
So setting up a centralized theme. Why do we want a centralized theme? Well, you may know already when we have a component system, we wanna also showcase our brand, our colors, our typography, right? And having a centralized theme means that you can actually control everything from a single place, right? Which is pretty cool and reuse things across. So instead of hard coding colors or hard coding stuff, even typography stuff, you can just have one single place where you have both your colors, both your typography, and reuse them across, right? With no dry code, okay? Dry code is bad, guys. Avoid that.
Anyways, you have also access here to colors for Material UI. It explains to you that we're using the Material foundation, right? And if you look at this tool right here, which is a pretty cool tool, because you can do a few things here, but I was also building this tool when I was part of Google, so that's FYI. I should not say that, but this tool was built in Angular, which is a terrible decision. But, anyways, that was back in 2014, so it was a long time ago. Anyways, what I want to show you here is how the material color scheme has been implemented and how it works. So, if you look here on the left side, we have all the different hues, red, pink, purple, right? And then on the top, you see the different, you know, like colors, 50, 100, 200. You can click on them and see them, right? These are, you know, like all the different tonalities of the color, right? It goes from the lightest to 900, which is the darkest. You also have access to the accents, but we're not gonna cover that, all right? Anyways, I'm just showing, showcasing to you, like, some of these capabilities. Then you also have access to the secondary just in case you want to change things here, all right? And see how it looks in different UIs. Fantastic. So, now, now that you know a little bit about the color scheme, I want to also showcase to you this generation of colors, which allows you from a single color, generate all the different tonalities, right? This is pretty useful because just if you have a brand and you have one color, you can get the whole list of colors by using this. Just pretty cool. You have access to the complementary, analogous, and the triadic, right? You can also see this in color tool if you click here with the colors that you selected, all right? Cool. Anyways, typography. So, typography in Material UI, they also use the Material Foundation and it has like all the different sizes that you can reuse across your app. It goes from H1, H2, to S3 all the way to H6. You have Subtitle 1, Subtitle 2, Body 1, Body 2. They were done text, they captioned, another line text. You can also add more as you want to, okay? And you can customize also the names of those typographies. But just in case you want to also see how this works is if you look at the typography here, this is a reusable component, right? And if you set the variant, if it's H1, it will be using H1. If it's H2, it will be using H2, right? Instead of going to the CSS and changing and hard-coding every single file with different sizes, you can have things consistent and you are reusing this across your app, all right? It's way better, guys, way better.
Anyways, that's why we want to centralize them. And we're gonna do it right now, all right? So the configuration is right there. I'm gonna be closing some of these tabs because we don't need them. Well, we actually need the server and we need to also have our app, sorry about that. But in SRC index, this is the main file that we wanna add our theme to inject the theme in our app. This is not going to inject the theme in our storybook because as you know, index.js is not rendering our storybook server. Here you have these two imports that you can grab them. You can also grab everything before the three dots right there and paste it right there. And then you can also copy and paste this root.render and replace our root.render, right? And if you notice there is a new high level component here called theme provider that you can inject the theme, this theme right here. So if you look at our React app, you're going to see right away that our bottom color has changed to red. Why is that? If you see here, it says palette primary main, this is red 500 where using that one for a primary. If we change red to red, 700, it will be the darker version of the red. And this red right here, you can also see that on the color tool. It's the same red is the default material red. So the 700 right here is this one. This one right here is the same one. All right, So you can also access to 900 and see it darker or you can all the way to the lightest 100, and you see it. And look how cool Material UI is, right? As soon as you change the color to a color that is pretty light, it will change the text color for you by default. So it's accessible, all right? You don't need to be making sure things are accessible. These are like coming for free for you. You know, pretty useful stuff. In any case, the red button, I was just showing you this, but let's make it blue. It's cleaner. So let's make blue 500, for example. Well, that's pretty light. Let's make it 600 instead. Okay, that's fine. Great. We have our theme right there. Fantastic. Things that you can do as well is if you look at the theme docs, well, there is a bunch of information here, but give me one second. Actually, if you look at the theme docs on the typography, because we're gonna do something pretty cool right now, is you can add a topography prop on the palette. And this topography, we can change, for example, our font family. Let's say like our font family is Arial instead, right? Wait, did that work? No, but give me one second. Yeah, here you go. So, you see like as I set the typography to font family Arial, I see it right there, okay? If you look at our app.js, this P right here, we can start replacing that to typography instead. So, you can say import typography, and we can also do this instead, so we can have these components coming from just one liner, in one liner. Just be careful with these guys, because these add some bundle size if you don't have a specific Webpack builds. I think version five onwards, this is fine, but version before Webpack doesn't really work well with this way of importing. The reason being is if you do that, this is going to add all the library every single time that you do that. So, if you have a lot of different imports and different files, this is going to add a lot of bundle size that you don't need. So, that is why I don't recommend this approach if you are not using a modern version of Webpack. In any case, we're adding this typography component and we're going to replace our p tag with typography. And we don't need the edit code, whatever. Edit, add, and save, let's see. Okay. Edit, add, and save to reload. Anyways, we're going to change the variant as I saw, as you saw before, to h1, and look, it's so big. Oh my God, what's going on here? Let's do h4. H4 looks a little bit better. But, what's going on with our button? Something happened with our button. Oh, because I went importing it from material UI. We don't need that, right? Our button is our button component. It's not our material component. We already have our own custom component and their components button. That was a mistake I made. Sorry about that, guys. And now, now we see our typography, our button. We can also add some sort of like, you know, a space between the two. So I'm going to introduce you to a Box component, which is also, it's like a div, but you can do cool thing with Box. With Box, you can add a margins. Margin-top, for example. Again, you can add like, margin-top and it's specified, let's say like, like three. And three is actually, and we will cover that in a second, is actually 24. And the reason being is the baseline that Material UI uses.
11. Theme Customization and Storybook Integration
The Material UI provides a grid system for baselines. The margin can be adjusted using shorthand properties like MT for margin top and MB for margin bottom. The typography and colors can be customized at the theme level. The button can be modified by changing the font weight. The theme can be applied to Storybook by adding a new decorator and moving the theme configuration to a separate file. Absolute paths can be used in Storybook by adding an alias in the main configuration. The decorator allows for the addition of high-level components to stories. Restarting the Storybook server may be necessary for changes to take effect.
The Material UI, every single baseline is a grid. And I'm gonna be covering that in a second. But, I'm not gonna go there right now into that because there is a section talking about that in a second. But just, what I want you to understand is three here is 24. Because it's a multiplication of eight. So if I said one, it would be eight. If I said two, it would be 16. Three, 24. And you may ask, this is terrible. Why are you doing that? We will cover that in a second, all right? It may don't make sense to you right now, it will make sense once we get there.
One thing we can do as well, is margin top that I added there. So there is some space between the two. I can also call it as MT. That stands for M, margin top, all right? If I wanna do margin bottom, I can do MB. You know, it's margin, M, bottom, B. If I wanna do M left, how is that? So it would be ML, right? That's not gonna work there. But anyways, when I do that, and I added this box, this box at the end of the day is a div that you can, I don't know, like do cool things around it. Anyways, we have that. Our button is looking nice, our topography is there. So, and coming back to our theme, the cool thing about this is you can also specify like the different variants at this level. So, we're using H4, right? So, if we go to our index and change, and add H4 and then add font-weight bold, you can see that right away our H4 is being injected there, right? So in one file, we can specify the values of every single typography we have. And there is H1, H2, S3, H4. As I mentioned to you, we have all of these already to be used, and we can also add more, right? We can customize our fonts too. But this is a sneak peek of what you can do with the theme. So we did some color injection, some typography injection, and we're gonna remove this Arial because Arial is terrible. Let's keep it as Nunito, how it was. I think it's not Nunito, to be honest. I think it's using Helvetica. So let's change that. So our font family should be Nunito Sans, and here you go, here we see it. It's right there, fantastic. If we want to change our button, we can also do it at this level, all right? As you saw on the topography, it is Button Text too, and the variant of the Button Text is Button, all right? So what we can do now is on button, we can set our font weight to bold, so it's easier to read. Let's see it, let's see that. Here you go, so now it's bold, easier to read. There are two ways that you can change your button, right? One is from your button component or also from your theme now, right? You can change some of the stuff at this level, all right? Cool, so now we're gonna continue, we change our button, now it's better, 500. Well, I use 600 here and I added some more stuff that what you are seeing right here.
And now we need to do the same for Storybook because our Storybook doesn't have any theme, all right? So in order to do that, we need to add a new decorator into Preview. So under Preview JX, we see these parameters, file, right, which has some configuration for our controls, but we can also import our theme right there, all right? So we're gonna import the theme. Well actually, our theme is not in SRC theme, all right? Our theme right now is index, so what we can do now, because we don't want them to conflict with each other, we're gonna move this theme to a different file so it can be re-used in our app and also in a Storybook. So, how do we do it? We're gonna create a new folder under SRC called Theme, under theme we can create a new file called index.js, and we can just move our theme stuff, the theme provider we don't need it, and we're gonna export this theme as default, right? Export default, create theme, and then under our index, we can just import the theme that we have under theme. Look how simple that is, the import now that we have absolute paths. It's way easier, right? Theme is under theme. So simple. So now, we'll look at, let's double check our app, so our app is working fine, fantastic. We'll move things around, so we don't duplicate code, and our preview. Now, we have SRC slash theme right there, okay? Great. So, also if you wanna use absolute paths in a storybook, you can do it from main, all right? But you need to add the alias right here. So if I do that under components, I will be able to use absolute, well, in this case, it will be shortcuts, right? It won't be absolute anymore. So, I want to preview, and I can just take the same approach as I was doing before. And we also need to add this decorator right here, all right? What this decorator does, it allow us to add high-level components on top of our story. Our story is what is rendered on the iframe. In this case is whatever is under dot stories. So, if you want to add contexts, or you want to add other providers, you need to do it at this level, all right? And this is the function of decorators, pretty much. So, our storybook is complaining because probably we need to restart our storybook server. So, we have to restart that.
12. Exploring Addons, Theme Provider, and Icons
We explored the addons in the main.js of Storybook, including interactions and links. We imported the theme provider from MUI and added theme stories for colors and typography. We were able to see the changes in our Storybook and make configurations at the theme level. Additionally, we showcased the colors and design tokens available in Material UI. We discussed the material icons library and its usefulness in adding icons to components.
And I'm seeing a question from an hour ago, sorry Ernesto. So, what are the addons in the main.js of a storybook for? So, if we look at those, those are like essential things that you can get, for example, if you see the addon interactions, that is the tab call interactions. If you want to learn more, you can just click here, and it's actually giving you a 404. That's why I didn't understand what this was. Yeah, we need to ask the storybook team to update some stuff here, but there are also essentials. The essentials are, I believe the ones that you have over here, and I think also the actions, and I think the links, the links is a very weak one. Where are the links here? I think these are like related to the docs, but we need to double check that. We can do a quick search on Google and see. So, how this links the stories, all right, cool. So yeah, this links the stories, it allows you to pretty much like have your stories linked in one single file. Not sure if it was useful, Ernesto, but hopefully you got the point here. Anyways, there is something going on here, our theme provider is not defined, all right. How do we import our theme provider? So if you look at the index.js, all right, this has already our import, for some reason, I think I didn't add it there. So that was a mistake. I will be updating the docs as well. So you need to import also the theme provider from MUI, all right, and this is probably gonna keep complaining. I know, look, it's showing up right there, fantastic. And I don't know if you notice it, but we already have the theme. We have Nunito, the font weight is bold. So we have our theme now in both a storybook and our app. All right, fantastic, great, where are we? All right, we added theme stories. We already did that, no, okay, this is cool. So I have two snippets here. All right, and what we're gonna do is under stories, so SRC stories, we're gonna create two new files. All right, this first file is called, it's gonna be called typography.stories.jsx. And another one, we're going to call it colors.stories.jsx. I find this very useful because you can actually reuse this in any storybook you want to do. This is a snippet and it showcases your theme at storybook level, all right? So feel free to use it. So if you click on the snippet link, you have access to the code and you can just copy entirely and paste it. I believe this one is the colors. Okay, the colors and then we're gonna do the same for typography, all right? So the typography also the link, so I'm gonna grab it and paste it onto typography. This typography, by the way, is coming from here, from the MUI docs. I have made few changes so it's a story. So if we look at our storybook, it's not showing up, interesting. Why it's not showing up? Oh, I had to hard refresh. If you hard refresh, you'll see it. So you're gonna see a new section called under library theme, and we have the colors, all right. And we have our typography as well, all right. So at this level, we can see how our typography could be used, all right? This is pretty cool because you can see here in a pretty... in a glance what's going on, all right. We changed the H4 to phone way to bold, right. So at this level, we can also make configurations, right? Let's say that H1, we want to change it to phone way to bold as well. And we are seeing it now, right. And so at this level, we can make all the configuration we need, and we know what's going on, and then we can reuse it. This also helps, you know, other Teams members to come here and understand what is the single source of truth, like how are things being implemented from a reusable level. And the colors, you can also see the colors that you're using. These, by default, are coming from Material UI, but let's say that instead of this purple right here, right, we want to change it to red, right. So what we do is under palette, secondary, we can change main to red 400, and we need to import that under colors. So we import the material colors. And you see it right there. By just setting up the main, the light and dark, and come to you for free. If you look at the color tool, those are the same as the ones that you see here in material. So anytime that you select a color, you get the light and dark versions, all right? So you see it there. I'm not going to have it red mainly because I am a Real Madrid fan. And sorry if you guys are some Barcelona fans here, but I cannot stand for something like this. I need to change that. So let's make it green instead. Sorry, guys. If you want to keep it red, keep it red. I want to make it green. It doesn't look that nice. But anyways, green 400, I'm going to keep it. You see as well there are some design tokens happening that I'm showcasing here. You have the secondary main. You have the secondary light. You have the secondary dark. And you got also the secondary contrast text, all right. Those are like properties that you can use across your app, right, and you don't need to be thinking about if it should be white or black depending on the accessibility contrast test that you need. Right? Come for free, it comes for free already. All right. We're not injecting these properties yet. We will be doing that pretty soon. But at this point, I just want you to get a sneak peak of our colors, our topography's now as part of our component library. Fantastic. Great. We did that. Then the next thing is we wanted to inject our icons to our components. Well, I'm not actually going to do it because I don't have a lot of time for this, but it's not that hard. But one thing I want to mention is if you look at the docs, these material icons are a library of over 2,000 icons that you can use from Material UI right away. You need to install this package. But the cool thing about this, these are like all the material icons. And let's say you want to find something related to a map, you can find it here. And if you click in any of these icons, you have the import right there. So you can just copy and paste it. And these are like SVGs. So you can actually change the color as well. So it's pretty useful, right? Anyways, I have an exercise for you. But we're not going to do it, which is enabling the ability to add icons in our bottom component. If you look at the bottom Docs, you will find information about it. But I'm not going to do it.
13. Installing Icons and Writing the Avatar Component
In this section, we install icons and start writing our first components, beginning with the avatar. Using a React library saves time by providing pre-built components that can be customized. We create a folder for the avatar component and add three files: Index.js, avatar.jsx, and avatar stories.jsx. By following the same principles, we can leverage existing stories to speed up development. We index the avatar component and add the necessary code to make it reusable. After encountering an error, we restart the server and resolve the issue by adding a default export.
In any case, I'm going to install the icons, though. I'm going to install them. So you have the snippet right there. You can do also NPM, as I mentioned before, but we're going to install the icons. That's the only thing we're going to do on this particular section.
And while installing, our next part is going to be very exciting. We're going to write our first components because the previous ones, we didn't write them. We cleaned them up a little bit. All right. So we're going to write a few components here. First one is the avatar. So this is the cool thing about using a React library. You already have all these components for free available for you. But you want to customize them to make it your own. So you start here instead of building things from zero. This saves a lot of time. And all of these components, as I mentioned, that are already providing you accessibility props, they are extensible, so you get a lot of things for free.
So here we also have a link here that says start here, because our friends in Anima, they created some stories for us already. Not for us. They have a sample storybook, but we can use that. We can leverage from it, because this way we can do things faster. Since we don't have all the time in the world, we're going to be adding those. So how do we add those? So with the same principles that we talked about before. We're going to create a folder per component. So under components, we get a new folder called avatar. And this avatar is going to have three different files, Index.js, remember. Then another one is avatar.jsx. Another one is avatar stories.jsx. And that's it. For now, that's it. So avatar stories.jsx, we're going to copy and paste this from there. And right now, if you check your storybook, you should actually see that. Let me refresh. Yeah. It's under material UI. Why is material UI? So as I mentioned before on the title, we can change that to move things around, but I want to move it to a library, because we want to keep our components on that library. So here you go. We see our avatar is right there. SRC is the photo. You can also change the letter and make it letter instead. You can also change the background color of your letter if you want to by using this control right here. As you know, there are also docs, but this component right now is not reusable. This is just a story. We cannot reuse this, right? If we want to reuse this, we need to add it on the avatar JSX. So first thing first, we're going to index this. And I'm going to go a little bit faster now, because this is like things that we did already. All right, avatar? So we import the avatar on the index. And then the avatar, we don't have anything here, so we can start adding our new React component, const avatar. And then we can not, this is the backbone of our avatar so export default avatar. And here, on the return, we're going to add all of this. All right? All of this is under stories, under the template. We're going to copy and paste it under return. And it's complaining because these arcs don't make sense. Those are actually like the props. So we will add the props on the first argument of our function, call it bgColor, letter, src. We can just remove the arcs. We don't need that. And there is also the letter. All right. I will call it character, but anyways, that's cool. All right, here you go. So our avatar, but avatar is importing avatar. That doesn't make sense. So you look at avatar.stories is using the MUI avatar, and we can just cut it and paste it here. All right. And then this avatar is conflicting with our avatar, so we should call it MUI avatar, all right. And now, on stories, we need to import our avatar that we just created. So import avatar from avatar, because it's right there. So we need to import it from the same folder. All right, cool. Now, this, we don't need it anymore. So our avatar can be injected this way, using the structuring. And something is happening with our render methods. Let's double-check. Now, you saw anything. Let me know. But it's something going on with our avatar for some reason. It doesn't like that. Element type is invalid. Sometimes the most stupid thing in the world. When things like this happen, I get confused. I'm going to restart the server. But I don't think it's going to work. I think there is something wrong. Oh, no, our avatar file that I'm not able to see it. We forgot default export maybe. Thank you, Epica. Export default avatar. But we have it right there. And all of a sudden it worked.
14. Creating Reusable Menu and Alert Components
Sometimes things like this happen, and it's just a matter of restarting the server. We have a reusable avatar, and now we'll do the same with the menu and the alert. We create a new folder for the menu component and add the necessary files. We make the menu reusable by adding props and updating the stories. Finally, we create a new folder for the alert component and add the required files.
I don't know. Sometimes this happens, guys. Magically this worked. Very interesting. All right, sometimes things like this happen. I think it worked because the server restarted. So when things like this happen, remember, sometimes it's just a matter of restarting the server. It shouldn't be that way. But because I added new files, that's probably something happened on the build. So now it's there, it's working. We have a reusable avatar. Fantastic. So we're going to do the same with the other two. The menu and the alert. So as we did with the alert, we're going to start here on the menu. And we're going to create a new folder under components called menu. And under menu, again, three new files, index.js, menu.jsx, and our menu.stories.jsx. That file is also going to get it from here. They call it MUI. I'm going to call it menu, because ideally this menu, we want to customize it as we want. But we're not doing it right now. We just like making them reusable. All right. So our menu.stories looks there. We can also find it. We have refreshed our storybook. And it's right there. Here's our menu. Look at that. We have our menu. But it's not reusable. So we need to make it reusable. And again, we can just get the index.js, paste it. And I don't know if you notice it. But this is all the time the same story. All the time the same thing. ABC, ABC, we should create a script to automate all of this. Anyways, our menu, we have it here under the template. We can copy the whole return and add it there. I pasted my avatar before. So I have some sort of template. And I'm going to change everything right there. I'll write the menu. I'll change that. And then this has all different components right there. If we look at the menu of the stories, we have all the import. So we can just copy those, paste them in. And these arcs, we need to change them. All right. We need to add them as props. So we have the open, we have the items. And I think that's pretty much it from what I'm seeing here, right? I think this is pretty much it. I think so. OK, so what I'm going to open the stories. And I'm going to remove all of these imports now. I'm using my own reusable menu component that I'm going to have as part of my story. So I'm going to replace this return with our menu. And then I deconstruct the arcs. And this menu list should be menu. All right. Now, it's there. Everything is working. Our menu works. This button right here doesn't make sense. It's not even doing anything. So I'm going to just remove that. I don't need that button. So I'm going to remove the import as well. And I guess I will keep this as it is. But here's the thing, guys. When you are creating your own component, you can also customize it. You can do more things. But I want to cover styling in a second. But this is how you start. You can start from there. This menu, you can also get it from the MUI docs. Here you can search it, and if you look for menu, you will have access to all this code that you can just copy and paste it. But in any case, you can take any approach you want. Right there. So OK, we have our menu. This label dashboard, we don't need that. All right, fantastic. So our menu is there. And then the last component that we have there is the alert. So again, we're going to start here, and we're going to create this new folder under components. Same thing again. It's becoming a little bit repetitive. So alert. We have index JS. We're going to be using alert.jsx and alert.stories.jsx.
15. Making the Alert Component Reusable
We made the alert component reusable by copying the avatar.jsx file and using it as a template. We removed unnecessary code and imported the necessary components from Storybook. We adjusted the title and description props to make the alert component extensible. The severity prop changes the icon automatically. We also removed unnecessary icons from the arg types. Finally, we discussed the possibility of moving the components to a library for easier importation.
So alert.stories.jsx. Again, we have a story here, ready for us to copy and paste it. And if we look at our storybook, our alert should be showing up right there. Look how cool is this. We can change the severity to info, to warning, to success. And this is pretty cool. Anyways, this alert is not reusable. It's a story. It's just a story. We cannot use it in our app. So let's make it reusable. So again, the index, we're going to index our alert. And then we're going to copy the avatar.jsx on the alert.jsx. We use it as a template. And then we can just get the return from the template inside alert stories of the JSX and paste it on the return. These are tried here. We don't need them as we did before. We need to add it as part of props. And we're going to start cleaning things here. Action. Avatar is not avatar. This is alert. We need to change that too. And alert is going to conflict with alert in a second. But we're going to import the rest of things from Storybook. So in the stories, we have all of these imports. And we can just paste those at the very top. And this letter, we don't need it. And I think that, OK, yeah, there is a conflict with alert. So let's do MUI alert instead. So there is no conflict with our component. And this icon right here, I'm going to remove it because the alert, by default, provides you an icon, I believe. Well, we haven't injected the component yet. But I'm going to delete some stuff. So we have the alert right there under the stories. We need to import a new alert. We're going to remove all of this code that we don't need. So import alert from alert. And on the template, we are going to just do the restructuring with ARCs. We're going to remove all these icons. We don't need that. And the thing is, we don't need the icon. But you can add any icons you want. But on the alert component, if you change the different severity, you see how the icon changes already. So information has this info button. Warning has this warning icon. Not bottom icon. So they are coming for free. So you don't need to change that. Then you have the title. This is an error. And the title is not working. This is fantastic. Why is it not working? Oh, look at that. This is how to code it here. It's terrible. So we need to add that. So in the title, that's why we're making this reusable, right, guys? We're making this extensible so that people can use it. And then we can add some sort of description to our alert component. Right, so we have the title. We have the description. And then, we can add here the args, the description. This is a very bad error. Let's see. Oh, I forgot to add the comma right there, I think. Oh, there's something going on. What else is going on here? I had to do hard refresh and it worked. But as you can tell, now we're making this extensible. We have the description. We have the title. And we can change things over here as well, the different severity props. This icon, we're not using it. So we can remove that from our arg types so it doesn't show there. And for some reason this happens. Oh, this icon right here in the arcs, we need to remove that too. Fantastic. So, and this action, you can also have it. I mean, I want to keep it. Anyways, I think the last bit is having these components on the material UI, I think we should move them to library instead. So on the title we would be changing that on the alert and also on the, I think the menu, we haven't done that yet. So on the menu, we can just change that. And I think that's pretty much it guys. So we already added this three components. Look how quickly we did it. They are extensible to be reused. Let's say we are in our app, right? And we have already this. So how easy is to import our alert? It's super easy. So what we'll do is import alert from components alert, and you can get from a storybook already on the docs, the code, you can just copy this. I mean, you probably wanna make these configurable depending, but I'm just showcasing the capabilities of having the structure this way on your component system. Right? I'm having a hard time here.
16. Writing Custom Styles with Emotion
We added the three components. We're almost ending the second section, implementation. We'll take a five-minute break soon. MUI offers various styling options, including plain CSS, style components, CSS modules, Tailwind, and Emotion. Emotion is similar to style components and is already included in MUI. Emotion and the SX prop provide powerful styling capabilities and allow you to inject theme design tokens. We'll cover the style prop, style on the SX prop, and how to use the style function. The SX prop simplifies the styling process and makes it cleaner. We'll write a simple custom style using Emotion in a separate file called button styles.js. This naming convention helps with organizing and finding styles in a growing component library.
So we see that there are here, there's something going on right there. I don't know what's going on. Something is grown. This is a very interesting error. Let's see. Mm-mm. Hello. There is something going on with this component. I don't know if something happened, but, oh. Something is being, oh, here you go. So our app is injecting some properties that we don't need, the CSS, the Salient Center. Okay, I'm gonna remove that. Okay, now it's working fine. We need to be careful sometimes with these things. But anyways, I just showcased the alert right there, gonna keep it as an error. But instead of an error, let's make it an info, because we don't have any issues right now. We can just call it like, hello, this is my app. Hello, I am making a reusable component application, whatever, here you go. And then we see it right there. All right, cool. Fantastic. All right, guys. So we added the three components right there. And just FYI, we're ending, we're almost ending the second section, implementation. And we're gonna take a five minute break once we do it. We haven't done that yet, but we're gonna get very, very close. The archetypes controls, I already showed you what they do. And the last bit of this is writing custom styles to our components. That's probably something that you were started to wonder, like how can we do it? All right, so if you look at the docs on mui, and there is a bunch of things that you can do in terms of a styling. You can use plain CSS. You can use style components. You can use CSS modules. You could use Tailwind. And until a year ago you could use JSX. Now called TSX. Look, I'm a big fan of JSX, and I use it a lot. But yeah, it's sad that they're moving away from it. In any ways, I have to say that mui now, the latest version is coming with Emotion. So you already have Emotion there. If you are a big fan of style components, and you need to install the style components on your own. So if you look here, you have the steps into how to install it. You have to install the library as well. That's FYI. All right? But the Emotion comes for free. And look, you may want to stick with CSS, but let me tell you what. If you use that, you're not gonna get the full capabilities of MUI. All the theme stuff that we already created, that is the foundation of what is coming next. The capabilities that we're gonna see now, you cannot really get it with plain CSS. So you may want to start setting your game to the next level, all right? So and here I'm gonna be talking about Emotion. I'm gonna do this in Emotion because that's how MUI works. Emotion is pretty similar as style components, by the way. And I'm gonna talk about style prop and style on the SX prop, right. The style is the engine behind this styling. The style style we're gonna add to the components now that is gonna inject the theme to our components is using this function, style, okay. And we're gonna cover that in a second. It's pretty simple. Don't get scared. And one thing as well is the SX prop. The SX prop is also like a game changer. I think it is super, super useful, super simple. This is a quick comparison of a style components API and using MUI system. So with SX prop, you can specify these props right there and start injecting your theme design tokens from there. Without adding all of these configuration. It looks way cleaner. You see the box. We use the box before already. You can have SX and you can add this stuff right there. Even move them to a different file. But if you see that, you see the color text secondary, those are like the design tokens that we added already under our theme. So this is how you will do it. Primary domain, secondary dark and you can add more as you want to. Which is super super useful. Anyways, we're gonna write just a very simple custom style so you see how it works. So under our button, this button CSS, we don't use it anymore. So we can just remove it. And we're gonna add a new file called button styles. JS. The reason why I call it button style JS instead of styles is the same idea as I mentioned before. If your component library starts growing and it has like 30 components in total. But if you have 30 components, I've seen that. You're gonna get like anytime that you try to find a file, you will get like all these styles showing up on when you try to find it. So it's harder to find those stuff. If you have the name of the component and the styles, then it's way simpler to find stuff, right? Like, let's say I wanna find button configuration so I just type button, and then I get the styles, the logic and the storage right away, right? It's way easier to discover things by following this approach. So how this works? I don't know if you guys are familiar with JSX, by the way, my slinch is complaining. I'm gonna just add this rule. This is not something that you wanna do. Here's lint, you probably wanna make a configuration for that. We're not gonna cover this in this workshop, but just for the sake of looking better than just having those things right there, I'm gonna just add this line on top, all right? So I added that those styles, we're gonna cover that in a second. This route is the name of the style that I will be using. I like to keep my styles outside of the component logic.
17. Styling with the Baseline Grid System
To ensure consistent spacing and alignment, Material UI uses a baseline grid system. This grid system aligns elements to an eight-point square baseline. By following this rule, elements can be spaced at eight-pixel increments or multiples of eight pixels. For example, a 12-pixel element should be adjusted to 16 pixels to adhere to the eight-point grid. The four-point grid can also be used, but we will stick with the eight-point grid in this workshop. The grid system provides a consistent and visually appealing layout for our components.
In that way, my component looks cleaner and it's way better for me to do it this way because to be honest, once you keep doing that is the same sort of organization model and things become way, way more cleaner elsewhere, all right? So what we're gonna do here is we're gonna import styles from bottom styles, right? And then what we can do now is our bottom, we can just set this styles right there. So we use the SX prop, all right? The SX prop, we're gonna use it, and now we'll say styles the root. I call it root because that's sort of like a consistent pattern I use, right? In any component you have a root level, right? So if you use that approach, you cannot use it elsewhere. So that's the root. So if you look at our react app, okay, can resolve our CSS. We need to remove that import.
This is the bottom. You probably didn't notice much, but this PX prop right there is setting the padding on the horizontal level. This is horizontal. X goes for horizontal. Y goes for vertical. So if I change the X to Y is PY. I don't know if you noticed that I mentioned that before P is padding, right? P stands for padding. And you probably ask again. Now, you didn't ask before, but three is not three, it's 24, right? I mentioned that before and the reason being, and I'm gonna explain this now, a material uses the material foundation, material UI uses a material foundation and that uses this baseline grid. This baseline grid means that everything is aligned to eight point square baseline, all right? This is a way for us to specify some sort of rules across our front end applications, right? If we use this baseline grid, things become better if we use that rule elsewhere. And what I mean using this rule elsewhere means that if you have certain pilings between elements, you need to keep this rule of eight pixels or a multiplier of eight pixels away. So this is an example right here. This element is 12 pixels, but that's grown, right? Because it should be 16, right? For certain things you don't care, but for other things you wanna do eight or you can even do four. That's also okay, right? But this is the four, sorry. This is not grown. By default, we have the eight and it is also the four point grid. In order to use the four point grid, I think you can make a configuration on your theme. But we're not gonna use the four, we're gonna use the eight. But on this four, you could see like this is a multiply, 12 is a multiplier of three, right? Multiply by three, you will get the 12. In this case, we'll be using the eight. I don't know if you noticed this vat component on the right side, you see these two little grid items, this is 16. So in order to specify that, with this rule, it will be two, right? Maybe at the beginning, it seems hard to follow, but once you do it, it becomes pretty consistent model. And let me tell you, it helps a lot in order to create things that look good. It's a very nice pattern.
18. Styling Components and Making Them Responsive
We made the button changes and explored the SX prop for styling. SX provides a simpler way to style components using camel case properties like P for padding and M for margin. We discussed the performance trade-off of using SX and the possibility of migrating to TSX. We added a more complex component, the cart, and made it part of our reusable component library. We also made our components responsive by using the responsive font sizes function from MUI. This allows us to easily make our typography responsive without much effort. Overall, we made significant progress in implementing and customizing our components.
Anyways, we look at our button, this button looks terrible, let's make it X as it was before. And now we have 24 pixels each side, you can also see it on DevTools. You see on the computed, you see the padding 24 on the left, 24 on the right, eight on the top, eight on the bottom, all right? We changed the text to capitalize instead of uppercase, we added some letter spacing, and the font weight change. If you are used to CSX, this is different, right? We're using a camel case for any single property. And as I mentioned, because we're using SX, we have other things that we can use to make things more simple. P for padding, M for margin, and you can also get more stuff than that. But those are like the pretty basics. All right, guys.
So we did that. And again, if you wanna add more styles, you can just add new properties on this object, and then inject those on your components, right? Sorry, here, right? So you will be using the SX prop. It's a pretty simple example, but I think you can get how this styling works from a very high level. I have here an exercise that we don't need to do now, but idea is to change the background color using the SX prop. Pretty, pretty simple. I think you can do it in a second. But anyways, now we are at the very end of section two. All right? Now we're gonna take a five-minute break. The most exciting sections are coming. One is implementation three, which we're gonna cover next, which is adding a more complex component, and we will be doing more stuff like adding some dark modes to our application as well as leveling this up. I was reading the thread about what Sebastien mentioned and Ernesto talking about the performance issue, and yeah, you guys are right. SX is not as performant as you can tell by using a basic class name, and but we're rendering here, like you're talking about like a thousands of style primitives, right? I mean, it's pretty large, but I totally agree. I mean, SX is pretty useful if you wanna do things quickly, but there is a disperse performance trade-off, I have to say. Is there something that actually is news to me? So thank you guys for sharing this because we are still using JSX the previous version, MUI in most of our projects. And at some point we need to actually evolve to the new version of MUI. And, moving JSX to TSX for us, probably is gonna be what we will be doing. I think TSX is supposed to be an evolution of that, but we will need to get a look into it. JSX was pretty performant for static styles. I think for the dynamic styles, emotion is better. But SXPRO is something pretty new. It's something that I started with version five and it comes for free. And it seems super useful for certain things in terms of like typing things faster and doing things faster and looking a little bit cleaner, but yeah, it's performance tradeoff is there. So FYI about it. Okay? You can also keep using class names instead or whatever engine you're using. As I mentioned before, there are a few engines that you can use for a styling within UI and you can find it on the docs. Anyways, I'm gonna move forward with the next section. If you guys got stuck or did you just got here, you can get ready for the next section by downloading the code and then making the installation on your own and starting both the app and the story book instance. And that is, you can find that as well on the first page of the workshop. Anyways, we continue, the workshop is already in this court. Just FYI, I have the link right there and I think also it's in the chat and Zoom so you have it there. We're gonna expedite things a little bit because we have a little bit less than 45 minutes and we need to cover a couple of sections, all right? So the first one is, I'm gonna delete, I'm gonna remove some of these tabs so it's a little bit cleaner and we're gonna add a more complex component. This is a cart component and as we did with the alert and the avatar, we're gonna do exactly the same because we're getting a lot of things here for free. As I mentioned, this is also part of the MUI docs and you can find them there. This component is pretty interesting and you're gonna see it in a second. So we as we did already before with the few components, we're gonna add a new folder called cart and then under cart, we're gonna add three new files, index.js, cart.jsx to make it reusable in a second and cart.stories.jsx. We're gonna paste that in and our cart should be showing in our storybook, right there. Okay, we have it there. It's pretty cool, right? We have the content, the variants, we can elevate the cart, we can set the footer, there is an image that we can also change that as we want to and remove the header. All right. So this component is there, we just copy and pasted it but is not part of our reusable component library, all right? It's just showing up in a storybook. So as we did before with the avatar and the alert, we are going to... I'm gonna use the avatar as the template to index the file as well as the log because it's very simple and I have it there. So the stories on their template, I can just copy the entire HTML and replace the return and change the names because it's not an avatar anymore, it's a cart and I will be also, these arcs are actually props, right? So we are gonna set them as props. All right, and then this arcs header, we're gonna add it there as well as the image, the image, the contents, the footer, and that's it. Now we need to remove that arcs key. All right, and these are some imports that we're gonna get in a second. So you look at the card stories, they have all the different imports on the very top, and we can just paste them in. And the card, we need to rename that because it's conflicting with our new component. And here you go, so we created our component and now we need to inject that onto our story, all right. So import card from cart. And we're gonna just remove all of this logic. And that's it. Here you go, so we got our card right there. Fantastic. So ideally, and this is an exercise that if we will have had time, we will have done that together. We can extend this card to also use our menu, which is here, right? Ideally, you want to also make that sort of reusable, extensible property, so you can inject that from the outside. At the end, you want to make your component as much of a reusable as you can, right? But I leave it up to you in order to do it, all right? So we added this component cart is injected. We're going to add it as part of our library that we have in a storybook. So this is going to complain for a second, but it's there. Right? We got our cart. Great. So we have our cart. We made this component right there. This is the last component that we're adding. Now we're going to do a few things here, all right? We're going to make components responsive. And this is pretty cool. This is very cool. So, MUI allow us to make responsive behavior in our fonts from our theme. All right? As you can tell here, there is a snippet that you can start using with REMS. But there is also this function called responsive font sizes and look how cool this is. Because if you look, for example, our typography and check how this is looking in different sizes, right? In mobile, or small mobile, or the tablet, it's not really responsive, right? But if we go to our theme and import these responsive font sizes, we can pretty much call our theme. Inside responsive font sizes, we want to add our theme. Then, all of a sudden, becomes all of them responsive. Look, I just did that, right? I just added this function and all our typography inputs are already responsive. This is pretty cool because you don't even need to think about doing much stuff. You're getting all of these for free. Now, if you want to make things more customized and particular to different pages, you can also use the styling engine to add that. But this, I think, is pretty useful and you can use it right away. You can add some responsiveness to your app from the very beginning. We'll look at our cart right now in a small mobile, and large mobile is already responsive, it's pretty cool. Very nice. I will now show you the breakpoints as well because this is very important.
19. Configuring Breakpoints and Responsive Styling
To configure breakpoints in Material UI, you can customize the default properties or set your own. The breakpoints include 0, 600 (small), 900 (medium), 1200 (large), and 1536 (extra large). You can set breakpoints under the Theme section. Injecting breakpoints from a responsive way is possible using the theme. You can use the theme.breakpoints.up('md') function to apply styles based on the breakpoint. Another approach is to use component-side media queries using the styling engine. This will be covered in the next section.
The way that you make configurations on your breakpoints, using Material UI, you need to know that there are six different properties, and these are like the default breakpoints that Material UI uses. One is 0, 600, which is a small, medium 900, large 1200, and Excel is 1536. All of these, you can also customize them as you want. If you click here, under Theme, you can set your breakpoints and set them up as you want. If you don't do it, the ones will come here by default, will be the ones that you'll see it. But let's say like our small version will be 400, so I do it here.
If I don't set anything, I will just grab the default properties. But this is pretty useful because I can also make all the different breakpoints just in one file, so is everything consistent and we can use it across. Another card is responsive, and that's fantastic. One thing I have to say is, if I will have had time, I will have shown you how you can actually inject those from a responsive way. But since we don't have a lot of time, I cannot do it. But I have here the docs. Docs allows you to actually find all the information you need. Like here, we are injecting from the topography H3. You can do it this way or this way, which is even better. Instead of our coding, you will just use the theme. You could do themed blend points app empty. Just for the sake of you can see it right now, I can do it very quickly with you. What I can do is, I can just grab that on the root and paste it here. Theme is complaining. The way that you inject the theme is by making this. This is also returning a function. You can do this. Let's say our font-size, just to see working, let's double-check. Our button font-size 24 M. Oh, it's app MD. MD, I think it was 900. This is how you actually want to make maybe a queries into your components using the styling engine. Pretty cool. You can also take a different approach. Instead of doing that from the styling side, you can also do it from the component side. That is what we're going to cover in a second.
20. Adding UseMediaQuery Hook
We're going to add a hook called UseMediaQuery hook, which provides three different properties for extending our material use media query. It can be used to determine if the screen is mobile, tablet, or desktop. For example, in our cart component, we can import the use media query hook and conditionally render the header based on the screen size. If you have any questions, please ask in Discord. We have added responsiveness and media queries to our website, and now we're moving on to more exciting things.
We're going to add a hook called UseMediaQuery hook, this UseMediaQuery hook is a snippet that you can just drag and drop it to your project and you probably know what hooks are. But hooks are super useful because these are reusable business logic that you can reuse elsewhere on your components. Under SRC we're going to create a new folder called hooks and we're going to add two files. One of them is Index.js and another one is UseMediaQuery.js. Then we will add the Index.js as well as this UseMediaQuery.jx. The reason being is if you will start adding more hooks, you can inject them on the index. So you can just do in the import, open curly braces and name of your hook, super simple. Anyways, we added this hook. It provides three different properties that pretty much extends our material use media query. It's more specific. If it's a mobile screen or a tablet screen or a desktop screen, you can reuse this in your projects if you find it useful. I think I find it very useful. So for example, in our cart, right? Since this is a more complex component, we can import our use media query from hooks, right? And this use media query comes with different properties, right? The first property, I think it was like, is a mobile screen. Yeah, so this is another way to know if it's a mobile screen or not. So let's say like, if we look at our storybook, right? Which for some reason is now complaining, okay, now it's not complaining. If we look at our storybook and we say that, if it's mobile screen not render the header, right? You can also see that working, right? Look at that. So in a small mobile, it's not working as soon as it's large mobile works because that's not how we set it up our mobile screen. If we change now, right? Like our, well, our hook is pointing to SM. So if we change in our theme, the SM version instead of 400 is 600. Then we won't see the header, right? Because this is for 414. So it's a smaller than 600, right? In any case, I think you now have like a very good idea into like how you can use media queries inside your logic and also in your styling files. But yeah, if you guys have any questions, feel free to ask me. I will recommend you to ask in Discord because that will be the only place that I will be addressing questions. As soon as we close the call, I won't be able to see anything. Anyways, here we are. We already added some responsiveness to our website as well as we did some media queries and now things are gonna be become very, very, very, very exciting.
21. Implementing Dark Mode and Theme Switching
We created two different themes, one light and one dark. By adding the dark theme, our component that was white before now appears dark. We also added the dark theme to our app, and now we can switch between the two themes. We added a mode provider using the context API, allowing us to change between light and dark modes at the highest level of our app. We created a new folder called Context and added the necessary files. We also added the mode context, which exposes two functions for setting and toggling the mode. By adding the mode provider to our storybook preview, we can now switch between light and dark modes. We can also switch themes in our app by using the context hook. This allows us to switch themes from anywhere in our app. Download the code to access the code that enables theme switching in the app itself.
So the first thing is we're gonna do like some dark mode capabilities and first things first, first let me tell you just a little bit about what this dark mode is. So, if you look at our theme, under theme, right? There is this palette right there. So, one thing you need to know is that if you look at the MUI docs, there is a section called dark mode. As you can see, there is the mode called on dark, you can specify dark, and it will by default start changing things for you. So, we're gonna create two different themes, one light, one dark.
So what we can do now, instead of exporting by default this one, we can create a new concert called light mode. Sorry, light theme, let's call it light theme because it's a theme now. So we'll create a light theme, and we're going to duplicate this. And down there, we're gonna have our dark theme. And just to start, just we're gonna just, just add this new prop called mode dark. That's it, right? Right now things are breaking because we had default before. Now, we don't have any default themes. So we need to change our main JX, sorry, our preview JX. And instead of theme, let's just use the dark theme from now. For now, we are going to use the dark theme, and look at that. As soon as we added the dark theme, our component that was white before, now it's dark. It uses the background, and it already does transformation for you, right? It's super cool. We also need to do the same in our app, all right? So in our app, we have the index JS. And this theme is no longer there. So we're gonna just set the dark theme. And in our app right now, I think we don't have anything to see yet. Well, the alert is changing the color, which is cool, but we will be seeing more. Fantastic, so here we are, we added the dark theme, but it will be nice to switch between the two, right? It will be pretty cool. So I added this snippet for you. This has like a contest util that you can also use in your projects. I find it very useful. So this uses the context API. I don't know if you're familiar with a context API. I wish I have time to explain to you what it does. But at the end of the day, what we're doing is adding some high level sort of providers that allow us to do certain things into our app. Like for example, if we wanna change our light mode to dark mode, this is how we will do it at the very highest level of our app. So, under SRC, we're going to create a new folder called Context. Context, and inside Context, we're going to have few files as you see on the snippets. First one is index.js. We can just copy and paste everything. All right. And then we are gonna add mode.context.jsx and copy and paste the whole thing as well. And then we're gonna do something in the preview but I'm gonna stop here for a second just to show you what's going on. So the mode context. Right? We have what important, the light theme, the dark theme. And it is also dark mode and light mode that we... two constants that we haven't specified yet. We will be doing that in a second. But this mode context is exposing two different functions. One is set mode and another one is total mode. All right? These are right now being memoized on our provider which means that this is not being rerun all the time when the app changes. Right? And then we also have the theme that when our mode changes to light mode we will be exposing our light theme. Otherwise we will be exposing our dark theme. All right? So this is the highest level of our app that we will be taking care of pretty much switching both themes. All right? So under theme, we just need to add two new constants. One of them is dark mode and another one is light mode. So we go there. Let's go there. So it's under theme. We will export dark mode and that's equal to dark and light mode. To light, right? So dark mode, so dark mode, we can also like use it here so we can clean this string so it's not hard-coded. Fantastic. So now this is clean and ready to go. And coming back to our mode context, this now is imported well, but I don't know if you notice it, but we are importing the theme provider here. So if we look at our app right now, on the index.js, right? We're importing the theme provider. We don't need to import the theme provider anymore. We'll be importing this new provider, all right? And we're gonna go there in a second. But before I go in there, I'm also showing you this index.js, which is exposing few things. One is it is exposing the context and the provider. All right? But the two things that I want you to get from this is just this new hook, which is a context hook, that we will be using to switch our themes, right? And then the provider that we will be injecting in the highest level of our app, right? That's it. So, now under preview, under preview in our storybook, all right? We need to add few things. Let's go one by one. So, the first things first, the very top, the first five lines, let's copy that and paste it. After, well, actually this theme, we can remove that. And we can also remove the theme provider on the top, right? This goes straight there, fantastic. We added there all of this, and we also want to add these parameters after the parameters, after the controls, all right? We're gonna add that. And then things are going to become interesting now. So, because we're using the theme provider, we need to add, to use our new provider, which is the mode provider. In order to do that, we need to have, we need to add a new story provider right there. So, we can copy this. We can actually copy the whole thing, guys, and replace the last bit. And just to explain you what it does, our decorators now is using our mode provider. Our mode provider is what we defined in our context. And then, we have this story provider, which will allow us to switch between the different modes. Now, we need to actually restart the storybook to see this in action, all right? So, let's, let's go in. All right, so let's restart a storybook. All right, fantastic. So, if we wanna change now to dark mode, look how simple it is. If you click on this icon right here, and then you click on dark, then you will see the dark mode version. If you click on light, you will see the light version. So what we did right now, guys, as, as by just importing a few, few logic into, into our files, is to be able to switch between these two modes from a single application. That is super cool, right? As you can tell, like, now, our storybook is working, but not our app, right? And I wish I have the time to show you that, but I will leave it up to you how to do it. I think you already have the information that you need to do that. I will recommend you to look at this file right here and also use the use mode context, which is the hook that we created to change the mode from anywhere in our app, all right? And yeah, that's pretty much it. Guys, if you download the code, you also have access to this code that I was mentioning that will allow you to switch themes from the app itself, all right? And now we're getting to the last section.
22. Exposing Components and Syncing with Figma
To expose your component system to other team members and non-developers, you can build a Storybook and deploy it using Netlify. Anima is a new plugin that allows you to import components from Storybook to Figma. Although it is still in beta, you can request access and try it out. By syncing your components with Figma, you can transition them into design assets. Install the Storybook Anima add-on, register it in your Storybook, and set the Anima access token. Restart the Storybook server and use the add-on to sync your components with Figma.
Things are gonna get very excited now. So when you create your component system, it's useful to have it locally, but ideally, you can expose this so other themes, other team members can find it, right? Especially non-developers. So the easiest and fastest way that you can do it is the one that I'm about to show you. So we're going to do a Yarn Build Storybook. You can also do npm run build storybook. And once you do it, a new folder will be created, right? We're gonna see that in a second. This new folder is called Storybook Static, all right? You can also change that. If you wanna change the folder, you go to Paket Json, and under Build Storybook what you need to do is add my, dash O, which is, goes for output and then the name of your folder. So you can call it dist or however you want, all right? But what this is doing is building a Storybook from public as well. Right? There are things in public that will be there. Okay, so we just built a Storybook. So now if you look at your files, there is a new folder called Storybook static. This is a pretty much like a static file, like even if you open the index.html, you have access to a Storybook, right? With the things that we did right now. In order to deploy it, you can use Netlify Drop. I will recommend you to actually create your account in Netlify because this is free guys. If you don't log in when you are deploying, your site I think is going to be live for a few hours only. But if you create an account and it's free, I think it's forever, so this is something that I will recommend you to take a look because it's useful. So you can upload it and you can also even change the domain name. Which is pretty cool too. Have you guys used Netlify before? No one answers. Oh yeah, Gabriel, that's cool. That's awesome. Alright, we got a 500, look at that. Sorry, I think I'm doing it wrong right? I am not exporting. I'm not importing what I should be exporting. Sorry guys, give me one second. I need to export a Storybook static. I don't know what I was exporting, guys. Sorry about that. It shouldn't take long though. So yeah, here you go. Your site is live and we have our Storybook deployed there. And all the different versions of our components, Dark Mode that we added is there. So anyone can come here and use the latest and greatest, all right? Ideally you have some CDCI integration in your GitHub so it deploys automatically to whoever instance you want. You can also use GitHub Actions for that, right. So this is just the quickest way to have your site out there. Anyways, you can also- and this is the most exciting part. What I'm about to show you. So right now, Anima is making a new plugin. I don't know if you know Anima, but Anima app, this is a prototyping tool that allows you to get code straight from design assets, right. It's a pretty cool app, but I think what they are trying to do now, which is pretty new because this is in beta. This is not available for everyone yet. So what you're gonna see now is pretty, pretty new. All right. You don't even have access to it yet. You need to request access, but it will be live soon. So keep an eye on this. So what we're gonna do is we're going to add this new add-on and you have this snippet here. The thing is at this point, I don't think you will be able to see what I'm about to see because you don't have access. So right now I, what I recommend you to do is see what I'm doing because it's the only way that you will see it until it gets live. All right. And I think that will be pretty soon. So that's why you have access to the code in once this is live, all right. So I installed the Storybook Anima and now I need to register they add-on on my Storybook. All right. I'm gonna add that add-on right there as we did with accessibility. All right. And then I need to set the Anima access token. Let me show you what I'm about to do. So I am showing like a new frame in Figma. I don't know if you guys know Figma. It's probably the most useful tool right now for designers to build any designs. So this is also something that you can open if you want to. But in Figma, when you create a new frame, it looks like this, right? And you can add stuff, right, on the Figma file. This is the empty project. So what I'm about to do is showcase you this plugin called Anima. All right, if I run it, I have access to a storybook but you don't have yet okay? That's FYI all right? I have some sync project I'm gonna forget that because I'm gonna start from zero with you. So, okay. So as I mentioned, this in beta guys you don't have access yet. You can request access. This will be live soon. But what I'm about to show you is this pretty cool feature which allow us to import our components with intuitive, you know, we can request to import our components from a storybook to Figma, which is getting the latest and greatest from our storybook. They are transitioning that into a design asset. So if you look at the docs we need to add also a new file called.env all right? And paste this storybook token all right? We need to space this token I'm using. All right. And now we can sync or your components but let me show you now. Now I have already installed anima. I just need to restart our storybook server, all right. So you probably notice that there is a new add on right here as the anima add on all right. So we go to our button and click there. This is the story got synced successfully. So we'll open our Figma and I just need to add this URL right here. A font is missing. Anyways, I'm gonna start generating the component. I'm generating now the component from the storybook. All right, this is not the one. Okay, here you go. Here you go, so, as you know, you've seen better. So things are like not working 100% right, but it will be there. So let me generate all the components, all right.
23. Prototyping with Production Components
Our components created in Storybook are now accessible in Figma, allowing designers to quickly prototype using drag and drop. This innovation enables us to create and put our components in front of users, gaining valuable feedback. By creating a component library in a short amount of time, we can prototype and innovate from the development side. This new approach, exemplified by Anima and NoCode tools, allows us to spend less time building and more time innovating. Thank you for joining us in this section on prototyping with production components. Stay tuned for future developments in Figma's capabilities. Have a great day!
Things are being generated. All right, I think we already have some stuff. We already have some stuff, look at that, guys. So our button now is here in Figma, right? These are like the usable elements for designers to use right away, and they're coming straight from our Storybook instance, right, like what we just configure on a Storybook is here with all the different variants, so you can pretty much come here and start reusing those on your application, right? So you go here on Assets, you can look for button, for example, that we created. This one is showing red. I think like there is something going on probably, oh yeah, here you go. So these properties right here, right, are the properties that we had in Storybook. I'm gonna put this side by side so you can see that. So this is a one-to-one match, but now we have the single source of truth in Storybook. Now the designers instead of creating a new library of component, they can just add it from our Storybook library, right? And if you see here these colors, we can change those to primary, secondary, success, warning, right, as we did here too, right, secondary. Oh, we have an error there. All right, guys, it is an error there. Undefined and really dark, whatever. Now it's not there, but I think something is wrong with our logic. We will need to fix that. But anyways, we have access to the different props, medium, small, by the way, this is not working right now, but this should be working. The disabled version as well. So we have access to all of the components that we created now, like the avatar as well, right? It's straight from a storybook. And the coolest thing about this, and this is something that is being developed, is at the end of the day, the goal is for all of these components to be useful as a prototype frame, right? Like if you go to Anima, you can actually preview this, and, look at this, and preview it, which in a second should be showing up. Forgive me, guys, because I'm showing you something that is in beta, so it's not that stable, but hopefully, we're gonna see it now. This is taking longer than it should. This is not normal. When this happens, hmm, something is going on. But in any case, what I was about to show you, and this works, this has worked for me, oh, now it's working, look at that, now we have access to our production element. Look at that, we already have the repo. So what we created on our Storybook as a production component now is accessible for any designer, even you, to put together a prototype pretty quickly, drag and drop components and create your own prototypes straight from your components in a storybook. That is super, super game changer, you know? And that is what I mean by innovation. If you guys wanna innovate, you want to start thinking about what is the fastest way to create something that you can put in front of users, right? And the closest to the product, that is, at the end, the best feedback that you can get from any single user. So if you can create this component library that we just did in less than three hours, right? And then start putting together prototypes, right? By dragging and dropping your own components into Figma and put this in front of users. At the end of the day, you are innovating, right? So that's why this is called Innovate with React, because we're not innovating from a design tool, which is the usual process. We're innovating from the development side, which is now super, super new. And as I mentioned, guys, there are few companies right now trying to do this. One of them is Anima. But if you look at NoCode tools, it's a very similar concept, right? NoCode tools are gonna help us actually, you know, spend less time into building things, which we love doing, right? But we can also go a step above than that, which is innovating. All right, guys, this is pretty much it. We almost run out of time. I showed you this last section of prototyping with your production components, because this is something super, super new. Like until now in Figma, even if you try, there is no way that you can use input fields, right? But this is going to be a theme happening pretty soon, which is super exciting. Anyways, guys, I hope you enjoy it. It was great sharing with you all of this. I hope you like it. Thank you so much. Have a wonderful day, and I hope to see you soon, guys.
Comments