Choosing the right tools for React component library in 2021
Tags: react, designsystem, a11y, cssinjs
Published: 2020-09-12 14:30:05

React ecosystem is huge and there is nothing wrong about it. You're free to choose the technologies you feel right for your product. But how do you choose them? Well, you have to try them all 😅 

In this series I will go over some of the tools that are currently in active development and ready to accept new users. It's not a guide on how to start a new component library just **now**, but rather a selection of tools to keep an eye on and consider to be used in the year of 2021.

## How to style in 2021?

*Before we begin... We need to decide on something very important...*

I worked on different Design Systems for Vue and React, with plain CSS and CSS-in-JS, and so I already formed my opinion on tools when it comes to Design Systems. It's time to admit: I like CSS-in-JS. After few months of hate I figured that the benefit of having 3rd party manager to map your props to produced styles outweighs the runtime cost. And for component library, one of the goals of which is to manage styles, you just need it.

But there are so many options to choose from:

- [styled-components](https://styled-components.com/docs) and [emotion]
(https://emotion.sh/docs/introduction) are two well-known options, but we know there are new, improved libraries around
- [treat](https://seek-oss.github.io/treat/) with potentially 0 runtime code, CSS is prebuilt during build time
- [glaze](https://glaze.js.org/docs/introduction) that uses `treat`, but with utility-first approach built-in (think [Tailwind CSS](https://tailwindcss.com/) – you compose classes to style an element instead of creating new classes for every case)
- [linaria](https://github.com/callstack/linaria) with 0 runtime and `styled-components` syntax
- [`@compiled` CSS in JS](https://compiledcssinjs.com/) smartly prebuilds your components to inject styles and use hashed class names, so 0 runtime and very fast

By this time, you probably feel that most of them promise the same. While `@emotion` and `styled-components` have the biggest userbase, all the new emerged options came from the need to have much faster runtime, doing most of the work at build time. That's why we going to pick a shiny new kid: [stitches](https://stitches.dev/) by [Modulz](https://www.modulz.app/). I liked it straight away because it's:
- has all the benefits of precompiled CSS-in-JS solution (SSR-friendly, little runtime, performant)
- generates atomic CSS, so your CSS won't be growing with your application scaling
- has easy installation – since it manages styles at runtime, you don't need to choose between `rollup` or `webpack`, struggle with `babel` plugins order execution, or your CRA/Next/Gatsby setup
- supports beloved [`styled-system`](https://styled-system.com/)-kind utils and tokens

## How to write documentation in 2021

*Phew*, much simpler choice, innit?
Yes, but actually no.
So, what we want for sure is to use `.mdx` format for our docs. Because it's a maintainable and scalable format for documentation.

- I guess the most popular option and a go-to solution would be [storybook](https://storybook.js.org/), it recently released major 6th version with many improvements and deprecations (goodbye `knobs`). It supports MDX format, plus can parse component's source file to show props table. But honestly... It's boring. We don't want people to come to our docs page, see storybook and think that we aren't serious just because we didn't invest much time into our Design System docs, as if we don't care. We do!
- [Docusaurus 2](https://v2.docusaurus.io/docs/) is always somewhere around the corner
- [docz](https://github.com/doczjs/docz) has been inactive for a while, it's worrying to start new project with a lot of deprecation warnings
- [React Styleguidist](https://react-styleguidist.js.org/docs/getting-started) is the boring choice for people who just want to get job done

But we are going to chose [dokz](https://dokz.site/docs):
- it looks nice out of the box
- it is very customizable
- it's easy to use

In the end, our choice doesn't really matter since [`mdxjs`](https://mdxjs.com/) is a separate project all these tools use. So `mdx` format is portable regardless the engine that powers our documentation site.

## Accessibility

I guess this the most important thing you should think of before starting a new component library.

>It's cheap to start from accessible Design System and maintain it. It is extremely expensive to make your existing Design System (and hence the app that uses it) accessible.

Thing is, accessibility is hard. The knowledge isn't widespread, business is often reluctant to invest into it until customers start to complain, designers often add accessibility as an afterthought. But if we want our product to succeed, we have to think about accessibility beforehand. Let's just name a few features where our component library can help with accessibility:

- use [accessible colors](https://web.dev/color-contrast/) with enough contrast
- auto-assigned or forcing to assign [labels](https://web.dev/lighthouse-accessibility/#names-and-labels) and [ARIA roles](https://web.dev/lighthouse-accessibility/#aria)
- make sure our components and compositions of components (`Modal`s, `Select`s) are keyboard accessible

And since accessibility is not a one-shot, but rather a continuous investment, it would be nice if there was a solution for our problems that will be improved over time. And **huge thanks** to `Adobe` for releasing [`react-aria`](https://react-spectrum.adobe.com/react-aria/index.html). It's a set of packages that helps you to make your custom components accessible! And the documentation is awesome. You not only see how to use a package, but also what it does and the benefits it provides.

## Now, where do we deploy it in 2021?

I've seen many different options, but the value [Vercel](https://vercel.com/) and Next.js provide is unbeatable. It's like you find your favorite ice-cream and you no longer want any other.

**Seems like we're done here and ready to start an actual development!**