Five ways to overcome negative thinking

Have you ever felt trapped in your own mind? Did you ever feel like your self-doubt is holding you back? A study shows that an astonishing 49 percent of entrepreneurs are suffering from at least one…

Smartphone

独家优惠奖金 100% 高达 1 BTC + 180 免费旋转




How to Build A React TS Tailwind Design System

What is this❓ Another “how to” article (post)?!

Yes, it is.

What’s in it for you?

Hear me out, it’s going to be worth it.

By the end of this post, you will be able to roll out a starting point for your own React + TypeScript + Tailwind + Styled Components design component library. Also, you will learn how to craft a workflow using powerful tools like StoryBook, Chromatic, and TSDX. Besides that, we will see and learn a bit about setting up stuff like React Testing Library and how to fix some of those annoying TS errors we encounter.

Moreover, I will attempt to explain why and how I went down this same road, presumably, in an entertaining and informing way 🤓.

The Background:

How To:

Suffix:

This whole post started with this tweet:

Seeing as it got some attention, I was bound by Twitter law to strap in, knuckle down and start typing.

For me, a lot of things around how I learn are a part necessity, part interest, and always a journey. It is important to understand the journey to realize if you have gotten to your destination.

So, here I am again, at a new place with new challenges ahead of me… I have written some stories about my humble beginnings, as well as some tales of other challenges I’ve faced as an engineer.

This time it started at a new company I joined not too long ago. About a month in, I was tasked with implementing a white labeling solution for one of the products to a client. For the sake of this post, what the company does is not that important. I was lead down this path because there are about 5 different applications and more in thoughts and planning. Being in the startup world, that’s just the way it goes.

Like I was saying, I started working on white labeling one of the products, not knowing much about what was at my disposal in terms of assets, eg. shared packages, component libraries, etc. I cracked my knuckles and started browsing through the different organizations Github Repos and started talking to people, trying to understand what is there that I can use to achieve the task at hand.

I ended up finding 3 different “common” React component libraries that weren’t used across all the applications, but some… It was divergent… Being a so to speak early-age startup, a lot of the code in the repositories was (and still is) “gung hoed”. This is not saying anything critical about other engineers, I’ve been there, done that…

In the end, I ended up with a solution I also shared:

It was clear to me that this is an ok solution for now, but this has raised the need to think about what we would need to do if some other client would want a white label of its’ own.

After discussing all the fun I had with the rest of my team and our former discussions around our shared packages, I was aware that there were processes that have started regarding building a design system, but were nipped in the bud for various reasons. I thought it was a good time to get this process going again and my colleagues and engineering leadership (luckily 😅) agreed as well.

What we aim to solve was reducing the number of components that are being written across the organization, share code, and be able to see what we have, while having a single repository to develop where we can manage versioning and distribution.

The solution is inevitable — we need a design system.

There is a lot of material out there about the correct definition of this term, as well as different opinions around, and I’ve read half a dozen posts and explanations what it is. It seems to be something else for different people in relation to their occupation.

For developers, this could be a shared component library (or package) like Material-UI, ChakraUI, BaseUI, etc. But, for designers, it could be a sketch file that has all the designs in one place. I’ve even heard product people call it a UI-Toolkit.

Design system workflow

That’s why for the first iteration I came up with this diagram:

This appeared to be a sound plan. However, things don’t always go according to our plans…

The whole process I went through with this piece of tech is worth a blog post of its own (I’ve even already written down the title in my notes: “The Bit they don’t tell you about Bit” 😅).

After meticulously crafting a whole workflow based on every shred of documentation and examples I could find, it didn’t sit right. Specifically, around the workflow, I imagined increasing the collaboration and velocity of my team and with Bit, there seemed to be too much overhead for any new coming developer to the project.

The bottom line was, Bit doesn’t play nice with Git. In my opinion, having a streamlined process that involves Git, code reviews, and design reviews are crucial.

Having said that, I have nothing bad to say about Bit. I think it has incredible potential, but it still is not fully there, it does not live up to the promise. I will keep a close eye on them though, they might just surprise us just yet.

As for myself, I needed a new plan…

The gist of it is that it is a Babel macro that runs at build time and creates Tailwinds’ critical CSS styles that are necessary for any given page as well as being extendable using CSS in JS libraries such as Styled Components or Emotion.

Once again, this seemed a solid plan.

Once I decided to ditch Bit, to get the ball rolling on this project I needed a way to build a pattern library, or more simply put a package.

The project’s tagline sums it all up beautifully:

It also comes with templates built-in, one of them was specifically what I was looking for react-with-storybook.

One thing that is good to mention though, is that TSDX comes with preconfigured Github Actions that test and build your package. Something that I didn’t know about it and misunderstood was all the matrix testing in .github/workflow/main.yml which has a node matrix configuration that spins up different types of operating systems to test the package on.

After that, I tried pulling the output code into our helpful example repo, and that seemed to work.

He did help me understand how to add some Tailwind intellisense for Twin:

But I have still not been able to get the above syntax to work in my library. I set it aside and moved on, as I had plans and willingness in my company to start developing the library. However, I am keen to get back to it at some point.

What I ended up doing was starting a repo from scratch and just going with Styled Components + Tailwind vanilla.

I could go on about the process of selling this whole idea back to my team and mention all the discussions around this project… But that’s probably not why you’re here 😉 …

For the sake of this post, I will start up a new repo and take it one step at a time as I write this. I will commit every step, so you can follow along or just check out the commits.

Let’s start by bootstrapping a new TSDX project:

Not much to write home about, but a good start.

If we open up our project in our editor this is the folder structure we should see:

Let’s breakdown the folders and files:

Other than those folders we also have the regular generic files like:

Let’s install our dependencies by running:

Next, we will need to add a postcss config in the root of our project:

Now we can initialize Tailwind with:

That will create a tailwind.config.js file in the root as well, where you can add and customize your configuration as needed:

Next up, we need to include Tailwind in our CSS, in our case, there are 2 things we need:

Alright, so now let’s add rollup-plugin-postcss:

Now we’ll create a tsdx.config.js file in the root and in it, we'll put the following code:

This is giving our postCSS path, which tells it what files we want it to run on. The minimize key is to allow us to minimize the output. The most important key here is the "inject". We set it to "top" to tell postCSS where inside the <head> of our page the CSS will be inserted. It's paramount for Tailwind as it needs to have the utmost priority of any other stylesheet.

Next, for part 2, we will create a tailwind.css (can be named anything else) file under the src directory and paste this in:

Great! This should allow us to get the job done.

Let’s check it out on the only component we currently have and see if it works:

Now we’ll run our StoryBook (yarn storybook) and have a look:

That’s a nice-looking “snozzberries” component!

At this point, it would be a good time to sort and prepare our package a bit so we can have more than 1 component. For that, we’ll change the name of the file that holds our beloved “snozzberries” component from index.tsx to Thing.tsx. Then, we'll create a new index.tsx file where we'll export all of our components and let TSDX do its thing:

Now, let’s see we haven’t broken anything and see that our test is functioning by running:

And we get this output:

You might be wondering: “What’s going on here?”

Next, we will need to point Jest at the correct type of files by adding this snippet to our package.json file:

Now we can run the test again, and behold the new results:

So now that we have all that going for us, let’s see how Styled Components gets in the mix…

First, let’s install the package and its TypeScript types:

Now let’s keep it simple and start by building a Button component (original, yes I know...):

We will need to add it to our index.tsx:

Add a Story for it, so we can see it:

And voila! Our very ugly button:

We can do better of course… Let’s remove our styles and add some Tailwind classes:

And now we have this handsome fellow:

This method allows great flexibility. How so? Say we now want to change the text color by the button “variant”. We can do this by adding a prop to our Button, and we can either change it by changing our used Tailwind class name or use the prop and change it via our Styled Component string interpolation.

First, we’ll add a variant prop to our component interface, and add 2 possible values:

Pass it in:

Hold on now! we have a TypeScript error!

Notice the squiggly line under “variant”? In a nutshell, TS is telling us “you are passing in a parameter I don’t know about”. Let’s fix that:

The tradeoff with option 2 is not having Tailwinds' utility classes and color themes to help us style things. However, mixing and matching both approaches is mighty powerful if you think about it.

One last thing that can be helpful is using a library like [tailwind-classnames](https://github.com/muhammadsammy/tailwindcss-classnames) which helps validate you are using correct class names, and if you don't TS will yell at you. It has the full capability and API of the known [classnames](https://www.npmjs.com/package/classnames) library, as it is just an extension of it.

With that out of the way… Let’s add it to our project by running:

Next, let’s add a test for our Button component:

We also want to make sure that besides rendering, we can click it. So we’ll check that as well:

Let’s try and make sure the tests work with yarn test.

But what’s this 😱 ?

The test failed due to a TypeScript error… 🤦🏽‍♂️

No fear! We can fix it… We’ll go back to our Button file:

And now we are all green!

One more test that is worth demonstrating is for our button with the dynamic Tailwind class. If you recall, we’re testing option 2️⃣ :

We can easily test that we’re expecting to have our text-white class when we're with the default variant and that we have the class text-red-700 for the warning variant. Let's add that test:

Now that we’ve tested our newly added component, if we’d like to gain more confidence that our button will work with our outputted and bundled code, we can use the TSDX example repo.

For that, we’ll build our code with this command:

Then we can move to our example folder and install our dependencies:

Next, we’ll import our Button and add it to our example App:

We’ll boot up the example app with yarn start, then we'll visit http://localhost:1234 and we should see this:

So, there we have our Button under our “snozzberries” component. Looks like it’s all working!

Once you’ve finished signing up, go ahead to your dashboard and create a project, you can choose an existing GitHub repo to start with. Once the project has been created, you’ll need to install the Chromatic package:

Then you can publish your Storybook with the following command:

This process will also guide you to complete the process and create an npm script for you:

Opening the “continue setup” link we get to this screen:

Now we can test and show how Chromatic works but clicking the “Catch a UI change” button. For that, let’s change something in one of our components. Good ol’ “Snozzberries” background is a good enough candidate:

Once again, let’s run the Chromatic script, but now we can use our newly added npm script that has our project token:

This time, at the end of the process we’ll see a message and an error:

Then going back to the Chromatic website this is what we see:

Now click on the “Welcome” component (our “snozzberries” component, that we should have renamed in its story 😬 ), which will lead us to the comparison screen:

On the right, we can see the new “state” of the component highlighted by green. Note, that this isn’t the actual color we put, but just “what has changed”. The three buttons on the top right can be toggled to show the actual new visual, click on the “Diff” will show us just that:

We can click “Accept change + continue”, which leads us to more explanations of the feedback process.

After we’ve finished developing, we want to make sure our package is ready to be published and consumed properly. For that, one more handy tool TSDX offers us is its size check script. The default size limit for our package is defined in our package.json under the size-limit property:

To run it we should make sure all of the code is built, and then we can run the size script by executing:

But what’s this?

We only have 2 components and the size is over 300KB??? That doesn’t seem right.

Finally, we can rerun yarn build && yarn size. Now our output will be:

Still not under the TSDX default of 10KB, but much much better. Like the green text in the CLI output says, you can increase your limits as needed.

It helps see what you’ve chosen as your Tailwind configuration. You can use npx on any project that has a tailwind.config.js file and just see what it has. Just run:

Besides showcasing your chosen config, you can hover over any class and just copy it with a click of a mouse.

In this post I am not going to dive into this subject, it deserves a post of its own. However, with the setup I’ve mentioned here, publishing to npm or github packages has some more setup and configuration entailed, but not much. The build artifact following these aforementioned steps is ready to be taken and put on any registry.

This is already a far too long post as it is 😅.

Here’s what Sascha had to say about it:

I hope I helped guide you through how to get a project like this going. I know I’ve enjoyed writing this, and I’ve learned a lot by doing so. I think the tooling I’ve mentioned in this post is pretty solid and absolutely helps boost productivity, but I know it’s not so easy to set up. That is why I wrote this down, so someone doesn’t have to go through the same hassles I did.

Surely, some tweaks and improvements can be made to this approach. Obviously, this is an opinionated way of building something like this. After all, I am one person and I have, like, you know, my opinion, man.

Hopefully (🤞🏽) if you’ve read this down to here, you’ve enjoyed this post. If you did, please share this around, comment, like, clap, and push the subscribe button 😜.

Cheers! 🍻

Add a comment

Related posts:

What Do Cataracts Do To Your Vision?

Early stage cataracts often have no signs or symptoms. Your vision will be affected as the cataract grows. It’s important to visit the eye doctor for routine eye exams, so that they can look for…

Create an API Gateway Solution for your APIs and Deploy it in Kubernetes with Ingress Controller

Hey folks..! In this article, I will implement a complete API gateway business solution for your APIs and will deploy it in the Kubernetes with an ingress controller. If you are not familiar with API…

RAJA96 Situs Togel Terbaik dan Terpercaya Dengan Pasaran Togel Terlengkap

Sebagai Situs Raja Togel Online di Indonesia, RAJA96 memberikan perlayanan ramah dan terbaik 24 jam non stop. Customer Service yang siap melayanin anda dengan ramah dan sudah ahli di bidang nya untuk…