Atomic Design and UI Components: Theory to Practice

Bringing Atomic Design into your UI component development workflow.

Uber’s basic component design system

Atomic design (by Brad Frost) is a mental model to help you think of user interfaces as a cohesive whole and a collection of parts at the same time. Through the comparison to atoms, molecules, and organisms, we can think of the design of our UI as a composition of self-containing modules put together.

Atomic Design helps you create and maintain robust design systems, allowing you to roll out higher quality, more consistent UIs faster than ever before. But, how can you leverage this when developing your own UI components?

Basics of Atomic Design in 30 seconds

Atoms are the most basic building blocks of our universe (forget about sub-atomic particles 😃). In UI design, these are the most basic elements such as buttons, inputs, labels etc. Through these atoms, we can compose larger elements that resemble molecules. In UI development, we can think of these atoms as our basic UI components. Each has its own defined and focused single-responsibility.

Basic elements are Atoms

Just like Atoms in the wild, these components can have different properties that determine their unique nature. These basic atoms-elements properties are the purest form of our style guide and our UI component design system.

When put together, these atoms form “molecules”. For example, a search input + label + submit button can create a “search form” molecule.

Atoms put together a molecule

When this newly form “search form” molecule is put into context such as a header, alongside other atoms and molecules, it becomes an “organism”. This header lives as a standalone creature, which can be used on different pages.

Molecules form an organism

When different organisms are put into the structure and are organized according to an underlying layout, they become a template of a page. When such a template undertakes a specific implementation of content, it finally becomes a specific instance of this composition called a page.

Then a template and finally a web page!

With this page, users will interact when they visit your experience, and this is where you see all those components coming together to form a beautiful and functional user interface. Cool, right?

UI Components as Atoms and molecules

That’s all well, but how do we implement Atomic design using real-world components, using pure JS or frameworks like React, Vue and Angular?

Actually, it’s more straight forward than you think. Components like row or input are our atoms. Sets of atoms can be brought together to create molecule-components such as a tab-based navigation bar. You can look around popular libraries like material-ui and see that it includes both Atom components as well as composed-components made from smaller atoms.

Most UI libraries include both Atoms and molecules. The reason is, people often seek pre-made functional pieces that can be used off-the-shelf. That’s ok, sometimes you can design and build molecules too. But, you should still aspire to modularize as much as possible, so when a change is needed, it will only be a simple manner or replacing one part with another, leveraging the separation of concerns principle- just like we do in microservices.

Example Atomic components: Tic Tac Toe Game

Tic Tac Toe game composed of Atomic components

As you can see above, using nothing but smaller Atomic components composed into larger molecule-components we’ve built a game-app. This game was built with components taken from this collection:

Some of these components are Atomic UI elements, like “input” and “button” taken right from the Prime React library with Bit. Other components are helper functions like “have empty cell” and “winner calculation”.

A “molecule” component: inputs, labels and a button

Larger “molecule” components put things together. These include the “square” component, which is also composed as part of the “board” component, seen below:

Board component composed using Atomic design

When everything is put together, you end up with a full-blown game application that is entirely composed out of smaller Atomic components, composed into molecule components and finally, into a fully functioning game application. Thanks to Bit, Atomic modularity becomes simpler than ever.

Atomic UI component library guidelines

So when approaching the design of your own Atomic library, you should think of the components you build as modular atoms and composition of atoms.

A great way to test your library as for how much it follows Atomic design principles is to try and break it down with Bit. If you can just isolate all the components and reuse each of them, you’re doing well. If you find out every component requires the entire library, you should improve modularity.

Meaning, you should aspire to reduce the coupling between components in your library to a minimum and increase the reusability of components as much as possible. This can be easier said than done, but here are a few tips.

Minimize global or redundant dependencies for components

Make sure each component has only the minimal dependencies it needs to work. Avoid coupling a low-level component to larger parts of the library or even to the whole library. This goes against the natural hierarchy of Atoms, molecules etc, and will make it hard to compose new pages using the highly-coupled Atoms. You can find out exactly which component is dependent on which other components/packages/files by running bit add (and then bit status )on your components, so that Bit will automatically calculate the dependencies for each component and present them as part of the unit.

Styling should not couple components

Avoid styling methods that go against composability and reusability. Instead, favor techniques that turn styling themes into Atoms just like any other component. Then, you can compose the logical components with the styling components to instantly create new instances and compose new things. You can share all of them, both logic and style components, with Bit so you can just choose & match off the shelf whenever you are building something new.

Indpednatly build, version and publish components

Version, pack and publish each component as a standalone module. Using Bit you don’t have to refactor your library. Just create a Bit workspace, track the components using bit add , link a compiler to each component, and use bit tag to version all of them. Then, when you update one component, Bit will prompt you to bump the version only for this component and the components depending on it (one command).

Developing in modularity lets you compose the library itself, with full control over changes to individual components (and their dependencies) without having to double through the whole library and update everything.

The people using your components can install only what they really need, and compose it as a new Atom right into their own apps. They can even get updates just to the Atoms they use, and not the whole library.

Build and Test in isolation

Build and test each component in isolation from the library, to make sure it works as a standalone unit that can be run anywhere and in other projects.

To avoid having to split your library, use Bit to isolate each component with its dependencies, link it with a relevant compiler and tester, and just run the build and test process in full and total isolation from the rest of the project using the bit build and bit test commands. When you export them to bit.dev, they will also run through indepdnat CI for every component.

Leveraging Atomic components tooling

You can use Bit (an open-source tool for component isolation and reuse) to organize a set of Atomic components and compose them together to build larger components and eventually, compose multiple entire applications.

Components collected from different apps and libs

It lets you isolate components from any library or app with all their dependencies, and helps you build and test them isolated from the project. Each component can then be versioned and published independently, and when changes are made you can only update the components affected by the changes, so it becomes easy to control and develop atoms and molecules.

It also lets you compose components together to create larger pages and apps. You can use it to enhance your own UI library with Atomic capabilities, such as Atomic isolation, build, test, versioning and publishing of components. It’s a very powerful combo with your UI library, to leverage Atomic design.

For this example, Bit was used to modularize the Prime React open-source UI library into Atomic standalone components. Now, we can compose these component-atoms together to quickly create new functionalities and apps.

Conclusion

The beautiful thing about Atomic design is that it’s the most effective way to build things: out of smaller, focused and independent pieces.

This is how the universe works. It’s also how design works, and thankfully, how our software works. When you implement Atomic design, you really implement the principles of modularity, reusability, single-responsibility, separation of concerns, SOLID and everything else that can help you build better and more maintainable software. It will also make like easier next time around when you’d like to reuse existing components to build someth§ing new.

Thanks for reading, I hope this was interesting and useful, and please feel free to ask anything below. I’d be happy to chat. Cheers 👏