Atomic design is a way of organizing web development by break design into components. It is an ideal solution for large service provider with multiple online services. Below is one of the ways to implement atomic design (with traditional web project structure).
The core concept of atomic design is making design and code base consistent and reusable by sorting component based on its category. Following the idea, the code base will become a categorized reusable library that could support related projects / products
The implementation of atomic design is a process of sorting component with categories and a creation of independent components
Figuring out the category of each component is the first and the essential part of achieving atomic design code base. In traditional web project, incorrect implementation of categorization may lead to massive refactor process or complex modification across multiple components in the development cycle. That is why developers and designers shall work closely and carefully figure out the category of component before the implementation.
There are three main categories in atomic design: Atoms, Molecules and Organisms. To sort out component with atomic design, we shall analyze the component in two main areas: structure, scope
Component could be identified by its complexity (HTML structure).
Here is a quick checklist to identify simple components:
- Atoms: one element (HTML tag), no internal functions, always been consumed by another components
- Molecules: combine multiple elements (HTML tags), but NOT consuming the full width (edge to edge) of device, and always been consumed by another components, may have internal functions (Javascript), may have style alteration.
- Organisms: similar to molecule, but it always consumes the full width of the device, could be a used at root level (direct child of the page)
For simple component, this checklist should cover everything. For other complex components, we will need to consider the scope of the component.
Scope means the control area of the component, and components shall work like lego. For instance, the root padding of components is in the scope, but the root margin set shall be controlled by its parent component (if it is necessary). Following this scope set, any component shall be able to 'stack' on top of others regardlessly (like lego). This is important because component may include (stack on) other components. The list below demonstrates how component including works in atomic design
- Organisms can include other
organismsmoleculesatoms - Molecules can include other
moleculesatoms - Atoms can NOT include any elements
Incorrect scope implementation is a common and critical mistake in component categorization. It makes component harder or impossible to reusable for our future development. A typical sample of wrong scope usage would be: when an organism includes a molecule, it has to directly modify the element inside of molecule. See sample below.
Incorrect scope sample
<div class="organism-a">
<div class="molecule-0">
<input class="organism-a__element" /> <!-- should not be here -->
<div class="molecule-1"></div>
<p class="atom"> text, just text</p>
</div>
</div>This is incorrect implementation because the modification (impact via HTML, CSS Javascript) of molecule-0 belongs to the scope of molecule-0 and it should be private. This scope control is the base of atomic design: each components should be independent from outer components .
Back to this specific case, it could be that the organism-a__element is implemented in a inappropriate scope. Placing organism-a__element out of molecule-0 could be one of the solutions.
<div class="organism-a">
<input class="organism-a__element"/>
<div class="molecule-0">
<div class="molecule-1"></div>
<p class="atom"> text, just text</p>
</div>
</div>Or, it could be the case, that code base requires a middleware (like Redux) to support passing data between components. With the middleware, we could achieve the desired style changes or function calls via data communication. In other words, replacing organism-a__element with molecules-0__element and implement the update via data would solve the problem.
<div class="organism-a">
<div class="molecule-0">
<input class="molecule-0__element" /> <!-- update style via data -->
<div class="molecule-1"></div>
<p class="atom"> text, just text</p>
</div>
</div>With correct categorization, the components can be independent from each other. Now we could start to improve structure.
For the file structure, we could follow the Separation of concerns, and placing code and files in a "package ready" format during the development process. This will make our npm packages easier to generate. Below is a sample package ready folders.
src
|- atoms
| |- button
| | |- index.css
| | |- index.html
| |- typography
...
|- molecules
| |- search-bar
| | |- index.html
| | |- index.js
| | |- index.css
...
|- organisms
...Here is how we could export and reuse this library for all online services:
- The whole
atomsfolder could isolated and shipped as the base style kit npm package (library) for the all npm packages. - Each component in
moleculesfolder could be isolated as an individual npm package with theatomspackage as its dependency. As the we covered in Scope section, this package could import other needed molecules as its dependencies as well. - Same as molecules, each organism could be exported as a npm packages.
The end result could be like this
Once we achieved structure update and package isolation, this library of npm packages can be used in any related online services development. From this point on, we could focus on integrating existing components to the services, building new component packages and maintaining existing library.
This will reduce development cycle dramatically and will achieve consistent user experience across all online services.