Building a component library requires a lot of thought and time. Every component has its own requirements, and we expect it to do a particular thing. Crafting a perfectly stable, robust component is a form of art. But what if you could automate that? Not all components can be created, but at least the basic components like a Button or a text Display components can be created automatically. You might ask how? Well, I will show you so let's get started!
React represents every component as a tree, where each child node is a react element with some props. We use the same idea to represent a component's structure as a JSON and then build an engine that goes through the JSON, creates an element for each node, and adds properties to it. We will get a component tree that can be compiled into a component.
Let us go over each node to understand it better.
metaDatastores the basic info regarding the component
layercan be considered as a node / element / wrapper in a component. This
layercan have children which can again contain layers
layerwill have the properties, styles and other data related to that element / layer
More on the complete structure of the JSON below.
A simple component can have the following properties: This button has the following properties:
meData- Basic information regarding the component, like its name, a unique ID, default variations, etc.
layer- The node of the component block (Eg. button, div)
properties- attributes or props of the layer ( class, tabIndex)
styles- css for the component block / layer
children- The sub-nodes / wrappers which can again contain all these properties
variations- The different types of a component. (Example: success button, tertiary button )
children property can be this whole structure all over again, just like every child can be a component in React.
There are 4 main steps involved in creating this engine
- Identifying a layer and creating an element of the layer using
- Adding props to it
- Identifying children, creating elements from them based on their type, and passing them as children to the current layer
- Extract variation properties and styles and override them
We use recursion where a node is created for every nested layer when it's of wrapper type and stop only when the layer is of type image or text.
Styles were a major concern while I was trying to make this work. I tried using inline styles, where I would inject styles with other props on each element and override them with the various styles. It worked well until I realized I could not add pseudo styles to an element, like
focus, etc. The solution was to create internal styles for every component and render the style element along with a component. This way I could define those states as a node in the styles object.
Every layer in the JSON has an ID. We use this ID to create a unique class name and attach styles to it.
So far, I have managed to create around 2-3 components using the engine.
The JSON structure of this component is simple. But it contains variations like primary and secondary Button.
The Input component contains three elements, the label, the actual input element, and the helper text. It has a nested structure because the label text, Input, and helper text are the children of the label element. It also has an
invalid variation, as shown below, which adds a red border to the Input element.
For more insight and an understanding of the underlying code, please check out the GitHub repository:
Make sure to star it!
While this is an interesting Idea, it can be considered just as an exploration. This is not at all scalable because creating complex components like Accordion is not at all possible for now. Some other concerns which need more thought:
- Currently, there's no way to add behaviors to it
- Only passing children are supported for now. It needs more implementation to enable passing more props, for example:
hrefto a link
- The component doesn't store any values, which limits its use cases widely
These are not just limitations. These are goals / additional steps that are needed to be implemented.
The Idea was not to automate the whole process. It was about creating an engine that would create components out of a JSON. But JSON can come from anywhere. If we automate the creation of the JSON, then we pretty much automate the whole process. For example, Figma files can be parsed to get layers and their styles using their API.
While it has a lot of limitations, the idea behind it is pretty interesting and out of the box. The next steps would be to make them store values and accept functions to make them interactive.