We use cookies to enhance your experience on the site
CodeWorlds

Atomic Design in React -- Building a galaxy from atoms

Atomic Design is a component organization methodology created by Brad Frost. The cosmic analogy is perfect: we start from atoms (the smallest particles of matter), combine them into molecules, then into organisms, until we build entire pages -- the galaxies of our application.

5 levels of Atomic Design

1. Atoms -- Smallest, indivisible elements

Atoms are basic UI elements that don't make sense to break down further:

1// atoms/Button.jsx
2function Button({ variant = 'primary', size = 'md', children, ...props }) {
3  return (
4    <button className={`btn btn-${variant} btn-${size}`} {...props}>
5      {children}
6    </button>
7  );
8}
9
10// atoms/Input.jsx
11function Input({ label, error, ...props }) {
12  return (
13    <div className="input-group">
14      {label && <label>{label}</label>}
15      <input className={`input ${error ? 'input-error' : ''}`} {...props} />
16      {error && <span className="error-text">{error}</span>}
17    </div>
18  );
19}
20
21// atoms/Badge.jsx
22function Badge({ children, color = 'blue' }) {
23  return <span className={`badge badge-${color}`}>{children}</span>;
24}
25
26// atoms/Avatar.jsx
27function Avatar({ src, name, size = 'md' }) {
28  return (
29    <img
30      className={`avatar avatar-${size}`}
31      src={src}
32      alt={name}
33    />
34  );
35}

2. Molecules -- Combinations of atoms

Molecules combine several atoms into a functional group:

1// molecules/SearchBar.jsx
2function SearchBar({ onSearch }) {
3  const [query, setQuery] = useState('');
4
5  return (
6    <div className="search-bar">
7      <Input
8        placeholder="Search planet..."
9        value={query}
10        onChange={(e) => setQuery(e.target.value)}
11      />
12      <Button onClick={() => onSearch(query)}>Search</Button>
13    </div>
14  );
15}
16
17// molecules/UserCard.jsx
18function UserCard({ user }) {
19  return (
20    <div className="user-card">
21      <Avatar src={user.avatar} name={user.name} />
22      <div>
23        <h4>{user.name}</h4>
24        <Badge color={user.role === 'captain' ? 'gold' : 'blue'}>
25          {user.role}
26        </Badge>
27      </div>
28    </div>
29  );
30}

3. Organisms -- Interface sections

Organisms are complex elements built from molecules and atoms:

1// organisms/CrewPanel.jsx
2function CrewPanel({ crew, onSearch, onSelect }) {
3  const [filtered, setFiltered] = useState(crew);
4
5  const handleSearch = (query) => {
6    const results = crew.filter(m =>
7      m.name.toLowerCase().includes(query.toLowerCase())
8    );
9    setFiltered(results);
10    onSearch(query);
11  };
12
13  return (
14    <section className="crew-panel">
15      <h2>Crew</h2>
16      <SearchBar onSearch={handleSearch} />
17      <div className="crew-grid">
18        {filtered.map(member => (
19          <UserCard
20            key={member.id}
21            user={member}
22            onClick={() => onSelect(member)}
23          />
24        ))}
25      </div>
26    </section>
27  );
28}

4. Templates -- Page skeletons

Templates define page layout without specific data:

1// templates/DashboardTemplate.jsx
2function DashboardTemplate({ header, sidebar, main, footer }) {
3  return (
4    <div className="dashboard-layout">
5      <header className="dash-header">{header}</header>
6      <div className="dash-body">
7        <aside className="dash-sidebar">{sidebar}</aside>
8        <main className="dash-main">{main}</main>
9      </div>
10      <footer className="dash-footer">{footer}</footer>
11    </div>
12  );
13}

5. Pages -- Complete pages with data

Pages combine a template with concrete data:

1// pages/MissionDashboard.jsx
2function MissionDashboard() {
3  const { data: crew } = useFetch('/api/crew');
4  const { data: missions } = useFetch('/api/missions');
5
6  return (
7    <DashboardTemplate
8      header={<NavigationBar />}
9      sidebar={<CrewPanel crew={crew} />}
10      main={<MissionMap missions={missions} />}
11      footer={<StatusBar />}
12    />
13  );
14}

Folder structure

1src/
2  components/
3    atoms/
4      Button.jsx
5      Input.jsx
6      Badge.jsx
7    molecules/
8      SearchBar.jsx
9      UserCard.jsx
10    organisms/
11      CrewPanel.jsx
12      NavigationBar.jsx
13    templates/
14      DashboardTemplate.jsx
15    pages/
16      MissionDashboard.jsx

When does Atomic Design work well?

Atomic Design works best in large projects with many pages and components. If you're building a simple application with a few views, the full five-level hierarchy might be overkill. In that case, a simple split into

components/
and
pages/
is sufficient.

However, in projects on the scale of a space station -- with dozens of screens, forms, dashboards -- Atomic Design brings enormous benefits:

  • Reuse -- a
    Button
    atom built once is used in dozens of places
  • Consistency -- all buttons in the application look the same
  • Easy testing -- atoms are tested in isolation, without dependencies
  • Onboarding -- a new developer quickly understands where to look for components

Rules of thumb

  • Atom -- one HTML element or the simplest component (Button, Input, Badge, Icon)
  • Molecule -- 2-3 atoms combined into one function (SearchBar = Input + Button)
  • Organism -- a page section with business logic (CrewPanel with search and list)
  • Template -- a page layout without data (slots for header, sidebar, main)
  • Page -- a template filled with concrete data from an API

If you're not sure at which level to place a component, ask yourself: "Does this component make sense on its own, or does it need context?" An atom works everywhere. A molecule needs atoms. An organism needs molecules and business logic.

Go to CodeWorlds