apocalypse

dev

Creating my own Design System - roadmap and first steps

#Introduction

In the previous post, I told a little backstory and explained the motivation for creating a design system of my own. Now it's time to actually get to work. I will draw a little roadmap for everything I currently plan on implementing. The most important thing is how I'm going to organize this DS into an actual (re)usable code. There are a few challenges upfront, and I will tackle them in this post as well. I intentionally leave the design part of my DS for later. Firstly, I want to prepare the backbone for upcoming work.

#Separate package (monorepo?)

The first issue that I see in my blog application is how everything is intertwined - the logic and the UI lives together in one big repo and, as mentioned in the previous post, it started getting out of hand. I have a remedy for that - moving most of the reusable UI outside this repo, to a separate one. Most likely the monorepo. This is a big challenge on its own, as I never actually set up a monorepo project, but my use case fits perfectly, so I will roll with it.

Alright, then. What should I move outside my main app?

#Theme config

As a general term, this may mean a lot of things. I think specifically about the tailwind theme.extends config. Why? Well, Tailwind already is a design system in a sense, because it is shipped with many opinionated theme values for things like spacings, font sizes, borders and so on. You could actually leave the defaults, and that would already be a great toolbox to shape your UI with. I extended my config with things like colors and animations, and that's what I would want to move outside to a reusable package.

When I researched the topic of how to reuse a tailwind config, I found out about presets. It looks promising and that's how I will approach the Tailwind config matter.

#Fonts

Yeah, when I mentioned the intertwinement, the fonts were part of the problem. I load my fonts with next/font, which returns a global className, that I can assign to an <html> tag, and then I can set the specific font family on whatever element I want, using CSS variables. It is quite a mess and I still don't know how to handle this situation well when I move the code outside. Maybe I will just leave the fonts in the main project? We'll see about that. Now, moving on to the biggest challenge.

#Components

In this blog project, I've been using Mantine UI library along with many of its ready-to-use UI components. It's a nice library, but it's also adding a ton of CSS variables to my page, that I have to scroll through when I inspect any element in devtools. It's not the end of the world, but I also find it quite hard to overwrite in certain cases, not to mention sometimes it clashes with the @tailwind base rules and I have to go great lengths to make it work together.

First, I thought that I could just re-export Mantine components and call it a day, but that would leave me in the same situation I am in right now, but now spread over multiple repos. I don't want to make it any worse than it's right now, and that's why I decided to just fork the library, truncate it a bit and also rewrite its CSS with Tailwind. I will start with the most common components, like the Button and various inputs, and then rewrite the less common ones. Obviously, I don't want to rewrite the entire library, but only the parts that I actually import and use.

#Icons

I still haven't figured out what to do with the icons. For now, I use a custom solution based on React Icons. I had issues with memory leaks when using React Icons, so I moved the library core and the icons that I use to my project. When I want to use a new icon, I run a script that I wrote in Rust, that takes the name of the icon, grabs it from the source code of React Icons and moves it to my project. It may be stupid, but it works and there are no more memory leaks.

Should I move icons to DS? Probably. Will I do it? Probably. Maybe not. We'll see.

So that would be my development roadmap for this project. As mentioned previously, I would like to start with the development, where I feel more comfortable, and when I have the backbone in place, I will start an actual design - colors selection, typography framework, components design and things like that.

#Testing and integrating with main app

That brings us smoothly to the testing realm. How would I work on my components and make sure they look and work as expected, before I run build and import them in the main app to see if they still meet the requirements? Storybook.

I didn't really do anything in Storybook yet, but I think that it's another tool that would fit my use case. I want to develop components in isolation, instead of importing them in the main app right away and test the validity of my UI there.

When it comes to the integration with main app, before I push anything to the npm repository, I would like to install it locally, and see if it works as expected. Package managers allow you to do that, so I'm relatively calm about it. I never pushed any library to npm, though, so when I make sure that my code works, I will have to learn yet another thing. But let's take one step at a time and get back to it later.

#Outroduction

The current biggest milestone is for the app (my blog) to still look and work the same way, but with a different architecture around UI. All that seems like a lot of work that would, for a long time, produce no actual difference in the final product. It may be true, but I really look forward to it anyway, because that seems like a perfect way to learn new aspects of web development, that I didn't get the chance to put my hands on yet. I'm sure it will be a good material for future articles as well, so stay tuned!

Related tags:

design
system
ui
custom
tailwind