Atomic Design for Developers: Atomic Engineering
By: Kris Guzman
Tags: UI Design, JavaScript, Programming, Web Development, React

Atomic Design for Developers: Atomic Engineering

A follow up on Atomic Design for Developers: Project Structure

In my first article on Atomic Design for Developers I discussed a good way to organize components in your project. I highly suggest reading it first, although I’ll briefly summarize it as well. If you don’t know what atomic design is, please read Brad Frost’s article on it.

So, the big question left after Atomic Design for Developers: Project Structure is how do we actually implement atomic design in practice? First we’ll do a quick review for new readers on atomic design, but those who read the last article can skip down to the Building the Google Search Page section.

We are going to take Atomic Design principles and turn them into Atomic Engineering principles

Quick Atomic Design Review

Atomic design is Brad Frost’s methodology for building design systems. The idea is that we can take the basic building blocks of living things and give our UI a hierarchical structure based on it.

Brad Frost defines five main stages of UI components:

Atoms Molecules Organisms Templates Pages

Atoms are the simplest form of UI, consisting of things like headers, labels, input fields, buttons, etc.

Molecules are a combination of atoms that form more complex pieces of our UI, such as a search field with a submit button.

Organisms build on top of molecules and orchestrate larger parts of the UI. This can include a list of products, a header, forms, etc. Organisms can even include other organisms.

Templates are where our pages start to come together, giving context to all of our organisms and molecules by giving them a unified purpose. For example, a template for a contact page will have organisms for headers and forms, and molecules for text fields and navigation bars.

Pages, as the name implies, is our final page with all its content. The difference between pages and templates is that templates don’t provide any content.

Building the Google Search Page

As a way to demonstrate atomic design in practice, I created a painfully simple rip off of the Google search page. You can type a query, click search, redirect to /results page, and see a list of hard coded results.

The article will focus on the high level principles, and the sandbox project will give a good reference for how to use those principles in practice.

Getting Started: The Mocks

Let’s pretend that our design team just passed us a couple of mocks that look like these:

Roughly Categorizing the Page Elements

Okay, so just by looking at the mocks we can begin to think about how the page elements would be categorized into atoms, molecules, organisms, and templates.

I find it helpful to start from large components, then see how we can break them down into smaller ones. First, let’s take a look at the app bar.

App Bar

The app bar is a fairly complex component. We have a profile image, menu items, and one of them is even a dropdown menu. Because our app bar is orchestrating smaller elements, the app bar is a good candidate for an organism.

What about our profile image, images link, and gmail link? These definitely qualify as atoms. They can’t really be broken down further.

That just leaves the “me” dropdown menu. This is a fairly complex component compared to our links and profile image. Organisms can be composed of other organisms, so it’s okay to categorize our dropdown menu as an organism as well.

Search Area

Our search area is pretty simple. It’s just the Google logo, an input field, and a button. These would all be atoms by themselves, but we should pay attention to how elements relate to each other. For example, look at the relationship between the search input and the google search button:

As a whole, we don’t see a complex management of components that we would expect from an organism. Molecules give a little more context to the relationship between atoms, and tend to search one specific function. This is why we will categorize the search bar + google search button as a molecule.

Search Results

So the part that says “Results for: awdwadwa” is just a header. I’d just classify this as an atom and move on.

The more interesting part is the search results. Given that each search result consists of an icon, a header, and a description, we may classify this search result item as a molecule.

What happens when we are managing a list of results? Well, now we are back in organism territory. We might have an organism called ResultList that deals with laying out our results.

In summary, here is how we categorized our page elements so far:

Atoms

Molecules

Organisms

What about our templates? Well, that should be pretty easy. They are just the skeleton of the mocks that we were given. In other words, it’s the page without specific data.

From Atomic Design to Atomic Engineering

Okay, so far we have looked at everything from a design standpoint. We broke down the mocks our design team gave us, but it’s still unclear how we actually want to build out our components.

If we want to get the most out of atomic design principles, we need to translate them into atomic engineering principles.

Here is a diagram giving the atomic design stages a little more UI development / engineering context.

Which Components to Build First

In general, I would suggest starting from the top of the hierarchy and working your way down (templates -> organisms -> molecules -> atoms) unless you are absolutely positive which category a component belongs to.

The smaller your components get, the more defined their role becomes. For example, remember how we came up with a SearchField molecule in the mocks?

Take a look at molecules/SearchField in the example project. While it is a valid molecule, did it really make sense to create one? We can only use it in one place in our app (strict styling & functionality), and the atoms that make up our SearchField can easily live in isolation.

Starting from templates and then refactoring components into organisms, molecules, and atoms give you the project context you need to properly categorize them. Atoms are usually easier to identify, but molecules and organisms, not so much.

It’s hard to avoid, but we can minimize the amount of refactoring and re-categorizing of components by starting from large to small.

Molecules vs. Organisms

This can be tricky. Atomic design principles differentiate the two by saying organisms are relatively complex compositions of atoms and molecules, and molecules are simple compositions of atoms.

How can we differentiate between the two categories in code? Here are a few signs you can look for:

If you have a component that is responsible for the layout or listing of a variable number of components (you may see a {children} or an {array.map(...)} somewhere in your react component's JSX), then you are probably dealing with an organism. If you have a component more complex than an atom that is reused often (such as a product in a list of products, an entry in search results, etc), then you have a molecule. If you are doing a lot of state management in order to orchestrate sub components (a form is a great example), then you have an organism. If you have a component whose only purpose is to give more context to its sub components (like a form field for city, state, and zipcode combined as an AddressField component), then you have a molecule.

This is pulled from the example sandbox project

Templates vs. Pages

The definition of molecules and organisms can get a little foggy in practice, but you want to make sure there is a clear line between pages and templates (and then rest of your components for that matter).

Templates are Presentational

Templates shouldn’t be dependent on application state. You don’t want to tightly couple it with redux state, react router routes, mobx, APIs, or anything specific to your app that wouldn’t allow templates to live on their own.

That being said, this doesn’t mean that templates will be free from external libraries. Just make sure you are acutely aware of what you are knotting into your templates. For example, you may have Semantic UI or Material UI components in there. Perhaps a Google Maps component is necessary for your project.

You may even use Redux (99% likely to be unnecessary) or a smaller state management library for non application specific state, which is probably fine too. Be careful though! The temptation to hook your app state to your components can be overwhelming.

Storybook is a good tool to verify that you are on the right track. If your template can’t be presented in a story without hooking up providers, stores, etc, it’s a sign that you are doing something fishy.

This is pulled from the example sandbox project

Pages Manage Application State

Pages make your web application come to life. Updating state based on API calls? Do that here.

Pulling in profile images for your carousel component? Do that here.

Using a HOC from Redux or React Router to get access to state or the history object? Wrap your page, retrieve it here, and pass it down to who needs it.

We keep everything in the components folder as loosely coupled from application logic as we possibly can. Pages manage that logic for them, and give them the data they require.

Pages, in essence, are the C in MVC. If templates make up the body of our application, pages make up the brain. It decides who gets what data, when, and how.

This is pulled from the example sandbox project

The Most Important Mindset

Develop as if you are building a component library.

That may not be your goal, but you will want to think that way, and here is why.

✔ Your Components Folder is Your Component Library

Damn right buddy. All that effort spent isolating your UI components from your application logic has made what is often times a massive team effort into a day’s worth of work.

The second your design team turns around and tells you they want to build a component library + design system, you can suavely take your sunglasses off and say, “way ahead of you pal”.

Plop that components folder into a new repo (plus dependencies), create an npm package, and import your component library into any of your projects. BAM! Component library done.

Even if there is work to do on the components themselves, whatever exists won’t break, and you can rest assured that things won’t explode due to a deep chain of dependencies on application specific logic.

✔ Storybook is a Match Made in Heaven

You can organize your storybook the same way you organize your components. This is great for both you and your design team and makes collaborating easier.

You shouldn’t have to worry about components breaking due to dependency issues because you built them to be as independent as possible. For storybook users, how many times have you had a story fail to compile because you didn’t wrap a component in some kind of provider?

When you move storybook into a new repo with your components, once again, everything will just work!

If it doesn’t work because your template component depends on React Router instead of being passed router props from the page, then Storybook will let you know that very fast.

✔ Unit Testing is Easier

How many times have you had failed tests because your component requires some HOC or injected dependency from another library? Could be Redux Form, redux itself, react router, or anything at all.

Atomic engineering is really just an enforcer of dependency injection. In the example project, when we type a query and click search, the app goes to the /results page using react router's history object and then displays the results.

If you look at the SearchField component in the example project, it doesn't care about the actual routing aspect. All it cares about is being given an action to perform on search. So when we test it, we can easily mock an onSearch function.

This isn’t a new concept. Atomic engineering simply helps you enforce this more easily.

✔ It’s a Great Workflow for Startups

90% of startups fail. Many are forced to pivot their product direction, but cannot stay alive long enough to do so because they had to completely scrap their original product and build a new one.

If you build your initial product with these atomic engineering principles in mind, you can salvage a shit ton of work when things go south.

Everything in the /components folder can be leveraged on your next project (except templates because of their context specific nature) with little to no setup needed, even if you aren't building a "component library" per-se.

Final Words

Please take a look at the example project and read through the comments. Even though the application is dead simple, it will give more context to the things I’m saying.

We start off with strict principles, but the important thing in practice is to be aware of the benefits & drawbacks of your architecture in relation to the project as a whole. I tried not to be too dogmatic in theory, because every project is different. These guidelines are meant to keep you on the safe side, and always questioning your code architecture decisions.

If you have questions, personal experiences you wish to share, or anything else, please leave a comment with your thoughts! This isn’t a bullet proof method, but I think it’s better than the traditional container vs component approach.