Why We Gave Up on the Idea of Using Styled System to Create Components, and Invented a New Wheel
Tags: react, javascript, webdev, cssinjs
Published: 2020-06-10 14:35:15

Hi everyone! My name is Alex. I’m one of the founders and lead developer at Quarkly. In this post, I’d like to share with you how the concept of atomic CSS, which we follow, together with the disadvantages of *styled-system* functionality (and *rebass* in particular) inspired us to create our own tool that we call Atomize. 

##A Few Words About Us
Our [Quarkly](https://quarkly.io) project is a mix of a graphic editor (like Figma and Sketch) and website builder (similar to Webflow), complemented by features of traditional IDE. We’ll be sure to elaborate on Quarkly in a separate post, as there is plenty to tell and show, but today we’ll focus on the details of the Atomize tool.

Atomize is the heart of the whole project, as it allows us to solve tasks that would be difficult or even impossible to handle using *styled-system* and *rebass*. At the very least, the latter solution is much less elegant.

If you don’t have time to read the entire post now, check out a brief description of Atomize on our [GitHub](https://github.com/quarkly/atomize).

And to make your introduction to our tool even more fun, we are launching a contest to build React components using Atomize. You can find out more [at the end](#contest) of this post.

##How It All Started 
When we got down to developing this tool, our team’s task was to give users the opportunity to code on two components, but without the need to have a separate CSS file. This was to keep the code as minimalistic as possible while retaining all CSS features in contrast to inline styles.  

The task was far from ground-breaking and, at first sight, could be easily solved with the help of *styled-system* (and *rebass*). But its functionality turned out to be limited for us. Or rather, we ran into the following problems:

* inconvenient breakpoints
* no option to write styles for *hover*, *focus*, and other behaviors
* mechanism for working with themes wasn’t as flexible as we needed

##Briefly About Atomize
![Atomize by Quarkly](https://dev-to-uploads.s3.amazonaws.com/i/rowm9u2zgj2y5vp3gv28.png)
Here are the key Atomize features:
* minimalistic interface
* option to use variables from the theme in composite CSS properties 
* support for *hover* and any other pseudo-classes
* short aliases for each property (like in *emmet*)
* opportunity to set styles for a specific breakpoint, all while keeping the markup readable 

That being said, Atomize is intended for two main purposes:


* creation of components that support atomic CSS and themes
* creation of widgets for the interactive editing in the Quarkly project

##Atomize. A User Manual
Before you start working with Atomize, you need to set up dependencies:

{% gist https://gist.github.com/Mobydack/1d5d81941f077f4c5af19f03a8d5f632.js %}
Atomize serves as a wrapper around a *styled-component* and has a similar API.

Just call the method using the name of the required element:

{% gist https://gist.github.com/Mobydack/da4eae8912d86027da021e1e960c9f95.js %}
As a result, we get the React component that can take any CSS in the form of properties.

To make it easier to use, we developed the system of alias properties. For example, *bgc === backgroundColor*

{% gist https://gist.github.com/Mobydack/a94ac7ffb00ffeda77b02db534019806.js %}
To see the full list of properties and aliases, follow this [link](https://github.com/quarkly/elementary/blob/master/docs/props.md).

Plus, we added the mechanism of inheritance in React:


{% gist https://gist.github.com/Mobydack/4dfe49d4154db09472e31249cab3e951.js %}

##Themes
This, I think, should be explained in more detail.

Quarkly themes are based on CSS variables. The key feature of Quarkly themes is that variables from themes can be reused both in props and themes. You don’t need to use additional abstractions, like template functions, and no additional editing is needed by the user.

To use variables from a theme, just describe the property in the theme and call this property using the prefix "--".

The variables can be used both in JSX:
{% gist https://gist.github.com/Mobydack/5292fe0a865995e68634ed949994cb4d.js %}
*(The color #04080C is available through the --colors-dark property)*

And in the theme itself:
{% gist https://gist.github.com/Mobydack/f9f4759f5ca1d2e933dfcd46e5f950b6.js %}
*(We reused a variable from the colors by including it in the borders theme)*

The shorter syntax is used for colors in the JSX markup:

{% gist https://gist.github.com/Mobydack/6ea11cf3ba6e2860ce3e20638e51137e.js %}

Themes have breakpoints for working with media expressions.
Any property can be prefixed with a breakpoint key name.

{% gist https://gist.github.com/Mobydack/3d7c7cfe9009677f1abdecb4310deb53.js %}

You can find the source code [here](https://github.com/quarkly/theme).

##Effects
The main difference between Atomize and the *styled system* is the "effects".

What are they and why do you need them?

Well, imagine you create a *Button* component, change its *color* and *border* and then… you realize you don’t know how to assign styles to *hover*, *focus*, etc. This is where effects come to the rescue.

When creating a component, just transfer an object with the configuration:

{% gist https://gist.github.com/Mobydack/bb46bac40aad65abc8214b4555157f06.js %}

The key is the prefix in the name of the property, and the value is a CSS selector. This is the same way we implemented pseudo-classes.

Now, if you specify the hover prefix for any CSS property, it will be applied to a certain effect. For example, when you mouse over it:

{% gist https://gist.github.com/Mobydack/5a26107d0208103cccc6747bffa27b68.js %}

You can also combine effects with media expressions:

{% gist https://gist.github.com/Mobydack/86a3c0f6d04a7f13b39580c725648251.js %}

##A Few Examples
Let's build several interesting components to illustrate the features I’ve described above.

Here are two examples:

* [a simple component that shows all the capabilities of the library](https://codesandbox.io/s/atomize-demo-skhjw?file=/src/Example.js)
* [a more complex example with a Pokémon card](https://codesandbox.io/s/pokemon-card-atomize-9pwom?file=/src/App.js)


Everybody loves Pokémon, don’t they? :)

In the second example, we used most of the functionality, as well as the external API.
##Wait! There's More
The second purpose of Atomize, as I mentioned above, is to create widgets in Quarkly based on custom React components.

All you have to do is wrap your component in Atomize and describe its configuration so that Quarkly can understand which properties can be interactively edited:

{% gist https://gist.github.com/Mobydack/5ea3cc633b4ff670f478b68fc248c484.js %}

The configuration fields for the component look like this:

* *effects* – defines browser pseudo-classes (*hover*, *focus*, etc.)
* *description* – component description that will appear when you mouse over its name
* *propInfo* – configuration of controls that will be displayed on the right panel (Props tab)

How to specify the props to be displayed on the right panel (Props tab):

{% gist https://gist.github.com/Mobydack/31cb8471f879141c97d6c3c5badb8ec4.js %}

Possible control options:
* input
* select
* color
* font
* shadow
* transition
* transform
* filter
* background
* checkbox-icon
* radio-icon
* radio-group
* checkbox

One more example, where we’ve added our custom component to the system and can now edit it interactively:

[![Atomize example](https://dev-to-uploads.s3.amazonaws.com/i/muub7i22q4g3jr1fshne.png)](https://www.youtube.com/watch?v=BzkV_g_q84U)

<a name="contest"></a>Yay! You’ve made it to the end :) Thanks for reading!  

##And Now It’s Contest Time!

We put our heads together and decided there’s no better way to fuel the community's interest in our Atomize tool than by following a path that’s as simple and logical as Atomize itself — a contest!

All information about the deadline, rules and prizes is available on the [official contest website](https://quarkly.io/contest).

But in short: to enter and win, you need to come up with a new (or find an existing) interesting and useful component and adapt it to Atomize requirements. And if your component gets added to Quarkly, you can count on some extra prizes from the team :)