Tailwind CSS, with its utility-first approach is known for speeding up the development process. Combining it with the power of React, let’s see how you can build a custom design system for your project to further speed it up, make it scalable and also easy to maintain.
Build a Design System with React and Tailwind CSS
AI Generated Video Summary
This Talk discusses design systems and how to build one using React and Tailwind CSS. Tailwind CSS provides utility classes for building complex layouts without writing CSS rules. Custom colors can be added to the Tailwind CSS config file, and font styles and text sizes can be customized. The entire Tailwind CSS configuration can be customized to meet specific requirements. Base styles can be added to the config file itself using a plugin. Reusable components can be created with Tailwind CSS, allowing for easy customization of size and color.
1. Introduction to Design Systems and Tailwind CSS
Hello everyone, I'm Shruti Balasah, a tech educator from India. Today, I'll be talking about design systems and how to build one using React and Tailwind CSS. We'll cover the importance of design systems, what they are, Tailwind CSS, advanced Tailwind configuration, React components with Tailwind, and component libraries for inspiration. A design system includes design language, design kit, component library, and documentation. Tailwind CSS is a low-level CSS framework that allows you to style web pages without leaving your HTML file. It has hundreds of utility classes and a wide range of colors and shades.
Hello everyone, I'm Shruti Balasah, a tech educator from India. Unfortunately I could not travel down to meet you all in person, but I'm still really thankful to be able to talk to all of you on this huge virtual stage.
I'm going to be talking about design systems today and how you can build one using React and Tailwind CSS. Any talk that has the word system in it has to be boring, right? But sorry, I won't make it boring for you. Here's a quick overview of what we'll be covering. Why design system? What a design system is? What is Tailwind CSS? How Tailwind helps with design system, advanced Tailwind configuration, React components with Tailwind, and finally some component libraries for inspiration.
Whether you already have a design system in place or hearing about this term for the very first time, I can assure you that you will take back something valuable in the next 20 minutes. I always start from the basics. So let's ask the first question, why design system? You have listened to so many talks since morning and surely design systems have popped up a lot. It's high time you implement a good design system in place.
So what exactly is this design system? It's not just some style guide or some component library. Ideally, a design system includes at least these four things, design language, design kit, component library, and documentation. Design language is the tiniest set of details that make up the whole of your front-end, like your brand colors, the type of fonts you use, including font sizes, font weights, and then spacing between elements, rounded corners, sharp corners, and so on. Design kit is the set of assets or graphic files the designer gives you. It can have icons, symbols, templates, mockups, and so on. Build libraries, I'm sure you know what this is. It's a set of reusable components like headers, buttons, form elements, cards, and hundreds of small building blocks. Finally, documentation brings together all these parts with references to each of them and lists the dos and don'ts. For the next 15 minutes or so, we will focus on these two parts of the design system, most important to us, as developers. Now enters Tailwind CSS. Of course, you've heard of it, maybe used it too, and some of you love it, some of you might even hate it. But for those of you who don't know what Tailwind CSS does, here's a quick two minutes intro.
Tailwind CSS is a low-level CSS framework that gives you the building blocks to style your web pages without having to leave your HTML file. No context switching. Tailwind has hundreds of utility classes like these, TextWhite, TextCenter, where TextWhite will set the color of your text to white and TextCenter will center it. Then something like this, BG Blue 200 will add a light blue background. Tailwind has about 220 shades by default that you can use. Here's just a sample. Tailwind has 22 main colors with 10 shades each, where 50 suffix is the lightest shade and 900 is the darkest. Next, the H20 that you see here is one of the fixed-height utility classes.
2. Using Tailwind CSS to Build a Design System
Tailwind CSS has utility classes for almost every single CSS property with commonly used values. Using these default utility classes, you can build even the most complex layouts without writing a single CSS rule. Tailwind CSS helps build a design system by providing a default configuration for a React app and allowing you to customize it based on a given style guide.
There are about 40 such classes, H1, H2, and so on. These are some samples from the documentation and the documentation is amazing by the way. You will find anything you are looking for within seconds. Then, something like this, H20, W20, you know, both of them about 80 pixels, width and height, then rounded full, so there's no need to use border, radius, 50%.. You can simply set rounded full. That's another great utility class. And this is one of the most amazing things in Tailwind. Look at that! By default it's a square, but after MDBreakpoint, that is for screens larger than MDBreakpoint, which is medium breakpoint, you can add a border radius, rounded full. Right? So you can specify any utility class using these breakpoints to change styles and without using any media queries as such. Much lesser code. And here's another thing, dark mode. You can use these dark variants by default, text gray 800 that is it's a dark gray color and in dark mode it's text white. We saw classes for text color, background color, border radius and heights. The same way, Tailwind has utility classes for almost every single CSS property with most commonly used values. Using these default utility classes, you can build even the most complex layouts like this and not have to write a single CSS rule. You don't have to invent class names and you don't have to constantly switch between HTML and CSS files.
Alright, now let's get to the crux. So how exactly does Tailwind CSS help build a design system? For that, let me close my slides and let's look at some real code. This is a React project I've created using create-react-app. I've installed Tailwind CSS following the documentation. It's pretty straightforward. I have also removed the default content from app.js and added just a heading here, paragraph and a link and just some utility classes here. Now this is what we have in the browser to begin with. Now here is our main file, the tailwind configuration file which is generated when you install Tailwind following the steps I just mentioned. This is the default configuration for a React app. If you want to use Tailwind as it is with all the default styles out of the box, you don't need to make any changes to this file. But to build a design system, this is your most important file. Assume you're given a style guide, something like this by your designer. I've taken this from Pinterest. It's just a really simple example.
3. Adding Custom Colors to Tailwind CSS
Let's add custom colors to our Tailwind CSS config file. By specifying the colors given by our designer, such as red and green, we can use them throughout our application. We can even include darker shades by using the object syntax. For example, we can define a default red color and a darker shade of red. The same can be done for green. By importing the Tailwind colors module, we can also include the default Tailwind colors if needed.
Let's say we have these base colors, red, green and dark blue and there are darker shades below. Also, we have black and two gray shades.
Now let's add these into our config file. Within theme block, add colors because we don't want to be using the default tailwind colors, we want to add the ones given to us by our designer. You can either say red or you can say primary, secondary, however you want to name them. I'll simply say red and use that value, which is hash FF357B. And similarly you can add green with the value given, which is hash 27EFDE.
So the moment you add these colors instead of, you know, BG blue 100, you can do something like BG red and that gives you a background red color. Similarly you can do BG green, you can also do something like text red, border red and so on. Basically you can use these colors anywhere you want. But we have two shades of red, right? One darker one and two shades of green as well.
To include two shades, you can also do something like say dark red, but that's not what we want. Let's use the object syntax to include that right here, like, you know, let's say the default red is this value, and dark red is, you know, whatever is the dark value there. Let me just paste it. Okay. And then you can do the same thing for green as well. Now, let's try and include these in our, you know, app.js, H1 class name. Let's say text red. See the moment I start typing text hyphen R, you can already see the auto completion here. And this is by the plugin Tailwind CSS IntelliSense, which is really amazing. The moment you change your configuration values, the auto completion, you know, automatically happens. So now let's say text red, and let's see if that works. Yes. So that is working. Now you have, you can continue to add those dark blue, black, and, you know, green and so on. Did you notice that now we have only this red and green colors. We don't have the blue 100, 200, and all the other 220 shades in Tailwind. But let's say you want some of those Tailwind colors. You can include them. You need to first import colors like this require Tailwind CSS slash colors.
4. Adding Colors, Font Styles, and Text Sizes
And then you can use the colors given to us, but we might surely need white. Next, let's customize the font family. The default font family used by Tailwind is sans, but we can change it to open sans or add another font like play fair display. We can also customize the text sizes offered by Tailwind and add additional ones. By adding all the design tokens to the config file, we create a design language that ensures consistency in styles throughout the page. Tailwind allows us to enforce various design properties, making it easier for developers to create consistent designs.
And then you can use let's say you need Indigo color, you can say colors dot Indigo and then you can use or you can say bg Indigo 5100 and so on. But since we're creating a design system, we wouldn't want to do something like that. We want the colors given to us, but we might surely need white. So let's just add that here.
OK, so this is about colors. Next most important set of properties in design system is font styles. Let's customize font family first, font family. And the default font family used by Tailwind is sans, that is it applies font sans to the whole of html. So anything you change here will automatically get applied. Let's say you want to use the open sans font and then the fallback like this, you can use the array to mention. So now when you say font sans you will be seeing open sans. Let's say you want to add another font, you can call it heading and when you say font we would want maybe play fair display and fallback being serif. Let's try this out, let's use this on our h1 by saying font heading you can already see that here. And yes, we have the serif font. Once again the default font family sans , whatever was there in tailwind is gone. This is okay for font family.
Now, text size, let's say, you know, there are so many text sizes that Tailwind offers like you can see text XS being extra small, SM, base, LG, XL and so on up to text 9XL. Let's say you want to keep all of these, but also include another, you know, text size something like text XS. Now to do that, if we add something like font size, sorry, font size here within theme, the available ones get overridden. Since we don't want that, remove it from theme and instead add it in the extend block. So whatever is available by default still remains and it's extended with these additional values. So let's say you want 0.6 rem. All right. So can you observe what exactly we're doing here right now? We are adding all the design tokens of our design language into the single config file. So this file is essentially our design language that we spoke about initially. Why is this important? Of course, we can create components and react, which we will in a minute. But components don't cover 100% of the design. It might cover even up to 70%, but the rest will still have elements with styles that you will have to write and those can easily become inconsistent with the rest of the page. With Tailwind, you can enforce the colors, font sizes, font weights, border radius, box shadows, padding, margin, breakpoints, and everything you can imagine. So the developer will only use the options available in the config file and maybe add new ones right here and then use them.
5. Customizing Tailwind CSS Configuration
In my opinion, the biggest benefit of using Tailwind CSS for your design system is the ability to customize the entire configuration. To do this, refer to the default configuration file and modify it according to your needs. The configuration file includes options for screens, colors, columns, spacing, animation, aspect ratio, background image, opacity, brightness, and more. By customizing these options, you can create a design system that meets your specific requirements. Alternatively, you can create reusable utility classes for commonly used styles, such as headings, to avoid adding multiple classes every time you need a specific style.
In my opinion, this is the biggest benefit of using Tailwind CSS for your design system. I just showed you how to customize colors, font family and font size. In the similar way, if you would like to customize the entire configuration available in Tailwind, you can refer to the default configuration.
To get that file, let me open a new terminal tab and let me do NPX Tailwind CSS init using the full option. Now, let me give it a different name because we already have the Tailwind.config.js. Let's call it TailwindFull.config.js because I just want to use this as a reference file. And here we have it. There. Can you see, within theme we have screens, which is essentially your break points. You can copy this if you'd like to modify, paste it here and then, you know, add an X's break point here, like 480 pixels. I usually do that. Remember that you cannot extend screens and add break points, it will just mess up. Only for screens, the break points, it's best to copy everything and edit here. You'll have to add all of the ones you need. You can also add 3XL and so on. And then we have colors, we just saw within theme, we have columns, we have spacing. I would like to keep all of this because whenever you do H8 and P11, it adds padding 2.75 rems, if you do W8 it'll add 2 rems, so we might need most of this and this is anyway not a part of design system. You can additionally add 100, 120, whatever you need. Animation, you can customize this, aspect ratio, background image, opacity, brightness and so on and so on and so on. I would ideally retain 75% of the stuff but change only things like colors, all the typography related classes, box shadows, border, radius, opacity and things like that.
So let me close this up. Let's make our heading actually look like a heading by adding text Forexcel and font bold. This makes it look like a heading. Now do you notice every time we need a heading we will want it to be bold maybe. We will need a particular size for h1, maybe text 3XL for h2 and so on. We'll definitely need font heading and we'll need a color as well. Usually this is consistent throughout your website. But adding all these four utility classes every time is too much. So creating a heading component might be an overkill. In such cases, you have two options.
6. Adding Base Styles to the Config File
One way to add the base styles is to extract them into a separate index.css file, but this creates an additional file. Instead, we can add the base styles in the config file itself using a plugin. By calling the add base helper function and specifying the elements to style, we can customize the font family, font size, font weight, and color. Combining these styles with the utility classes in the config file allows us to have everything in one place, ensuring our design language is consistent.
One is you can extract all of these and you can put them in your index.css file within layer base and say H1 and sorry using the apply directive, you can apply all of these and now this works. But this will become a second file. And I want everything to be in my config file itself. So let me remove this. Let's not do it like this.
Instead, let's add the base styles in the config file itself using plugin, for which let's import plugin const plugin. And now within the plugin array, let's call the function and pass an anonymous function within with which takes an object and we can deconstruct it into multiple helper methods. The helper method we need right now is add base because we want to add the base styles. And also need something like something called theme, which I'll tell you what it is in a moment.
Within this call the add base helper function and then specify the elements that you'd like to style. For H one, let's add a font family here. You need to use the CSS and JS syntax. And here I would want this particular value here, which is specified in the theme. So whenever you want to access a value in theme, you can use this theme function. So theme font family .sans. So that will give me this value here. Let's also add a font size. Sorry, font size, that would be theme font. Size. For Excel and also a font weight theme. Font weight dot bold. And now here, let me add only the color. Yeah, we can add that also in the config file. But I'm just showing you that both can be combined. That is, you get all these styles plus the additional utility classes that you add here. And great. Now, any h1 we add in the page will have those three base styles. So once again, we have everything in the config file itself. So awesome. This is about everything with respect to the configuration so that our design language is taken care of.
7. Creating a Reusable Component with Tailwind
We'll create a reusable component with Tailwind to demonstrate how to build a component library. We'll add styles to a link to make it look like a button, and then create a button link component with predefined styles. This component can be easily reused without specifying class names. We'll also add rounded corners and create a classes object to handle different styles, colors, and sizes. Finally, we'll combine all these styles using the class names NPM package.
The last thing we're gonna do now is create one reusable component with Tailwind so you get a basic idea for creating your own component library, the second part in the design system that we said we'll talk about.
So first for that, let me add some, sorry, I'll close this also. I'll close this as well. Let me add some styles to this button sorry, this link to make it look like a button. Let's say we need some margin top, we need some inline, we need this to be inline block and then some background BG red on hover. This needs to be BG red dark, even on focus, this needs to be BG red dark, then the color text white and then horizontal padding PX four, vertical padding PY two. Of course, this is a lot. You wouldn't want to add this every time you create a link, which is why we are gonna create a button link component.
To save time I've already created this right here. So here's a button link component with href, class name and children. We can directly use this here, replace this with button link and yeah, it's imported as well. Sorry. Yeah. Let's check. Of course we have the same thing right here. Let's also add some rounded corners, maybe rounded MD. Great.
We're using this component but we don't want to specify class names like this right here. So what we will do is, if you can observe there are some general styles here that all the buttons might need like inline block and rounded MD, but there are some specific utility classes like BG red, however focus tiles, all of these. This we might want to keep changing. We might need a green button or dark blue buttons like we saw in the style guide, and then these padding might vary based on the size of the button. So what I'll do right now is create a classes object with some base styles, then some styles related to color, and then some classes related to size. And here, I will take inline block from here and also rounded MD and add that here. Inline block, rounded MD. Then I will add the BG red and all of this into color. And then into size, I will add these. MD2, I would like to retain it here itself. All right? Now let's combine all of these using the class names NPM package. Let me import it first. Import class names from class names.
8. Customizing Button Size and Color
To customize the size and color of buttons, we can add them as props. By creating options for different colors and sizes, we can easily customize the buttons. The default size is medium with a green color, but we can override these defaults by specifying different sizes and colors as props. This basic example can be extended using prop types and enums for more robust customization.
And yeah, here I'd like to use class names. This also gives us the same thing, but we'd like to customize the size and color as attributes. So what we'll do is we'll add them as props here, but before that, let's create options, you know, red, and this would be red. And then similarly, let's have a green button. Similar to that, let's also, you know, change the size to give some options like SM, that would be Px2, Py1, maybe a smaller padding, and then maybe MD, that would be Px4, Py2, then Lg, Px6, and then Py3. Okay, and here, let's say size and then color. Let's add the default, sorry. Yeah, let's give a default of MD size and a default of say green, yeah. And here, now this would be color, and then size, because each one is now an object. Okay, this should work by default. We should have a green color and a medium-sized button, and perfect, we have that. We can customize this now using size equals, let's say, lg, and then color, sorry, color is red. Perfect, we have a slightly large button with red color. Of course, you can extend this further. This was the most simplest example. You can use prop types. You can use enums and make all of this more robust. This is really just a very basic example.