While designing development components is relatively new, design systems have been around for quite a long time, and have influenced the way we approach application development lately.
Design systems aim to set down documentation, rules and reasoning about a certain implementation of a user interface. It should also provide a UI toolkit, and cover most cases where it's applicable. This has already been a common practice in design studios, or when defining the corporate image of a brand and its applications. It's no different when done for software development.
It's common to start a design process defining colours, typography, sizes, how to use a logo in their different variants, or by explaining why there should be exactly the space of an 'm' character separation with the following text. All of those rules and decisions exist so as to make their later application in the real world easier.
But how does this translates into the digital world and into todays programming processes?
Brad Frost, in his article Atomic Web Design defined Atomic Design as a methodology for creating design systems applicable to web pages and html styling.
Atomic design provides a clear methodology for crafting design systems. Clients and team members are able to better appreciate the concept of design systems by actually seeing the steps laid out in front of them.
According to this, he defines five levels:
These would be the most basic building blocks of an interface. Usually attached to HTML DOM elements, they can also have information on colors and typography, sizes to be used, etc...
These elements are easily re-usable and easily styled, and serve as the foundation of a brand.
We are mostly going to find these elements, groups of atoms bonded together, in every implementation. They are usually visually meaningful, and by combination, they allow for functionality.
Organisms usually are groups of molecules that work together in the same section of a website. They are recognized as a unit in a website, and probably worth showing to clients. These elements are normally used just once in every page; think about headers and footers, or registration forms.
Templates (or Views) consist of a composition of different Organisms in the final visualisation of your design. They are like the blueprint of a page, and provide a context wherein the Organisms are meaningful.
These are the most specific of the design elements and show the website as it will appear to users. No more placeholder content, but a representation of what users are going to find navigating, with as much precision as possible.
The days of spaghetti code are over, rejoice!
Ever since Facebook made React public around 2013, and coined the term "Component-based architecture", it has been widely popular in todays development world, and all current frameworks have been revolving around this in one way or the other.
Component-based architecture aims to write code by encapsulating individual pieces of a larger user interface (aka components) into self-sustaining, independent micro-systems.
This makes much sense as the "Single Responsibility Principle" from SOLID states that there should only be one reason why you would change the implementation of a class or function. Similarly, our components should be following the same reasoning, and be as focused as possible; as independent from the rest as possible; as atomic as possible.
Most of the work we do nowadays in the front-end is made in React. This makes it really easy to import the components you need, delegate functions that would change the state of the application - all the way down to events triggered in the lower branches of the component tree (Atoms and Molecules) -, separate business logic and state from the UI, and be able to unit test each piece separately.
The good news is that using atoms is like playing with Lego. The bad news is, you would need to define your pieces. As many as you’d like to use.
Atoms are dumb components: most of the times they will be
stateless functional components, since they won't use any lifecycle hooks, with a very simple output.
You don’t need to redefine all HTML DOM elements, even if you do CSS-in-JS. Keep them as simple and re-usable as you can. If you have more than 4 optional parameters, that's already a molecule.
Molecules are still very simple, mostly stateless or with some local UI state information. They usually receive functions as
props to be able to fire from events.
Oftentimes, we would want these components to be
PureComponents or hold a strict logic on when to update them when the props change.
They could have simple logic on whether or not to show parts of their own UI (Atoms), but they normally rely on passed down props to display DOM elements.
As the different pieces bound together into an Organism usually compose a section of our website, these are the first components really holding the UI state, according to the global state or routes.
Your Templates are usually rendered from different routes in your application (this is no longer the case if using React Router 4), are fully connected to the global state, and usually even have no DOM representation at all, apart from bundling together several Organisms.
They would also have the definition of those functions referenced from Molecules to trigger after user events, and most likely, will be changing the global state or have application logic.
Usually, when working with highly re-usable components, the best approach is to have some sort of
src/shared/ folder, and then some
src/shared/molecules to import from. Most Organisms usually have a particular functionality within an area of your app, so it usually makes much more sense to store them within
src/modules/myFunctionality. Unless we are going to make a large use of them in different parts of our application.
When it comes to defining design systems, UI libraries take one thing as the main concern: re-usability. Keep your Atoms simple and re-usable, keep your Molecules wrapped around just one functionality, don't try to over extend. Your Organisms and Views will take care of the state and ui logic, and will give you app a layout.
Try to come up with as many components as needed, based on design mockups or desired functionalities, and always unit test them. It might seem slow at the beginning, but it will be much faster to compose Views later on, and moreover, they would have cohesion and performance.