Atomic Design

アトミックデザイン

Atomic Design を分かりやすく

Atomic Design(アトミックデザイン)とは、デザインシステムを理解しやすい単位に分解し、再組成する手法のことです。ちょっと難しく感じますよね?でも大丈夫、一緒に分解して見ましょう。

この手法は、物質が原子から成るように、Webデザインも最小単位から作られるというアイディアに基づいています。アトミックデザインでは、これらの最小単位を「アトム」と呼びます。

さて、ここで一つ例え話を出してみましょう。LEGO(レゴ)のブロックを想像してみてください。LEGOは一つ一つの小さなブロックが集まって、何でも作れるようなシステムですよね。アトムはまさに、これがWebデザインにおける最小のブロック、LEGOの一つ一つのパーツに相当するんです。

そして、これらのアトムを組み合わせることで「モルキュラ(分子)」が作られます。LEGOで言えば、個々のブロックを組み合わせて作った小さなツリーや車、人形などがこれにあたるでしょう。それらはさらに組み合わせられて「オーガニズム」を作ります。LEGOの世界で言えば、家や城、公園などの大きな構造体がそれになるんですよ。

このように、アトミックデザインはデザイン要素を再利用可能な部品に分解することで、一貫性と効率性をもたらします。それはまるで、LEGOのブロックを使って何でも作り出せるように、Webデザインも小さな部品から大きな構造体を作り出せるというわけなんです。

アトミックデザインをうまく使うと、Next.js や Jamstack、TypeScript などの技術と組み合わせて、再利用可能なコンポーネントを効率的に作ることが可能になります。一体ナンノコッチャ?って思いましたよね?でも、これがアトミックデザインの世界なんですよ。

どうでしょう?結局のところ、アトミックデザインは「一つ一つの小さな部品を組み合わせて大きな全体を作り出す」というシンプルな考え方に基づいているんです。そしてそれが、Webデザインの世界でも非常に有用なんですよ。凄くないですか?

Atomic Design は、元々ブラッド・フロストという Web デザイナーが提唱しました。この手法では、小さな部品から大きなパターンを組み立てることで柔軟性の高いデザインを実現します。具体的には、5 つの要素を組み合わせることでデザインシステムを構築します。

レベル 説明
原子(Atoms) デザインシステムの最も小さな構成要素。ボタン、テキスト、画像などです。 ボタン、テキストフィールド、画像
分子(Molecules) 原子を組み合わせて作られたコンポーネント。フォーム、ナビゲーションバー、ヘッダーなどです。 ログインフォーム、検索バー、ヘッダーバー
有機物(Organisms) 分子を組み合わせて作られたより複雑なコンポーネント。記事、サイドバー、フッターなどです。 ブログ記事、製品ページ、お問い合わせページ
テンプレート(Templates) 有機物を組み合わせて作られたページまたは画面。 ホームページ、サブページ、ログインページ
ページ(Pages) テンプレートに実際のコンテンツを挿入。テンプレートを使用して作成された、最も複雑なレベルのデザイン。 特定のブログ記事、特定の製品ページ、特定のお問い合わせページ

アトミックデザインは、Web サイトとアプリケーションのデザインと構築のためのシステム思考アプローチです。この手法は、デザインを 5 つの階層に分類することに基づいています。

これにより、小さな部品を再利用しながら柔軟かつ効率的にデザインを作成できます。アトミックデザインは、デザインシステムを構築するための堅牢でスケーラブルな方法です。また、チームがデザインを効果的に共有し、コラボレーションするのにも役立ちます。

Atomic Design を Next.js で実装する

Atomic Design を Next.js で実装するには、アトムからページまでをそれぞれコンポーネントとして作成します。

まず、アトムは次のようなテキストコンポーネントを作成することができます。

import React from 'react'

type TextProps = {
  text: string
}

export const TextAtom = ({ text }: TextProps) => {
  return <p>{text}</p>
}

次に、マクロアトムはアトムの組み合わせとして、次のようなボタンコンポーネントを作成することができます。

import React from 'react'
import { TextAtom } from './atoms/TextAtom'

type ButtonProps = {
  label: string
  onClick: () => void
}

export const ButtonMolecule = ({ label, onClick }: ButtonProps) => {
  return (
    <button onClick={onClick}>
      <TextAtom text={label} />
    </button>
  )
}

Organisms(有機体)

Organisms は、複数の Atoms や Molecules から構成され、単一の単位として機能するものです。ページの特定の部分を表します。例えば、ヘッダーやフッター、カルーセルなどです。

Organisms は、他の Atoms や Molecules から構成されているため、再利用性が高く、様々なページで使用することができます。Organisms の実装は、Atmosphere の例と同様に、各 Molecules のプロップスを通じて簡単に設定することができます。

import { FC } from 'react'
import Image from 'next/image'
import { Button } from './Button'
import { Title } from './Title'

interface HeaderProps {
  logo: string
  buttonText: string
}

export const Header: FC<HeaderProps> = ({ logo, buttonText }) => {
  return (
    <header className="flex justify-between items-center">
      <div className="flex items-center">
        <Image src={logo} alt="logo" width={120} height={50} />
        <Title text="Organisms" />
      </div>
      <Button text={buttonText} />
    </header>
  )
}

上記の例では、Header コンポーネントが Atoms の Image、Molecules の Title、Button を使って実装されています。Props として logo(ロゴの画像のパス)、buttonText(ボタンのテキスト)を受け取り、それぞれ適切に表示されます。

Templates(テンプレート)

Templates は、Atoms、Molecules、Organisms で構成された最終的なページのレイアウトです。ページの構造、配置、デザインに関連するコンポーネントです。Templates は、機能やコンテンツに依存することなく、独立して再利用することができます。

以下は、ホームページのレイアウトを表すテンプレートの例です。各コンポーネントを組み合わせることで、ページ全体のデザインや構造を実装できます。

import { FC } from 'react'
import { Header } from '../organisms/Header'
import { Hero } from '../organisms/Hero'
import { Feature } from '../organisms/Feature'
import { Footer } from '../organisms/Footer'

interface HomeTemplateProps {
  logo: string
  headerText: string
  heroText: string
  featureText: string
  buttonText: string
}

export const HomeTemplate: FC<HomeTemplateProps> = ({ logo, headerText, heroText, featureText, buttonText }) => {
  return (
    <>
      <Header logo={logo} buttonText={buttonText} />
      <Hero text={heroText} />
      <Feature text={featureText} />
      <Footer />
    </>
  )
}

つまり、Atomic Design は、構成要素をシステム的に扱うためのデザインシステムの考え方で、複雑な UI/UX をよりシンプルかつ再利用可能にします。

Next.js で Atomic Design を実践する

次に、Next.js で Atomic Design を実践する方法を見ていきましょう。まずは、Atomic Design の概念をベースに、Next.js での実装方法について解説します。

Atomic Design のパターンを Next.js で使う

Atomic Design で定義されているアトム、分子、有機体などの概念をベースに、Next.js でのディレクトリ構造を決めていきます。以下に、Atomic Design のパターンに合わせたディレクトリ構造を示します。

src/
  atoms/
    Button/
      index.tsx
      styles.ts
  molecules/
    Header/
      index.tsx
      styles.ts
    SearchForm/
      index.tsx
      styles.ts
  organisms/
    HeroSection/
      index.tsx
      styles.ts
    ProductList/
      index.tsx
      styles.ts
  templates/
    DefaultTemplate/
      index.tsx
      styles.ts
    ProductPageTemplate/
      index.tsx
      styles.ts
  pages/
    index.tsx
    about.tsx
    products/
      [slug].tsx

上記のディレクトリ構造は、Atomic Design の概念を反映したものになっています。各ディレクトリには、その名前に合わせたコンポーネントが格納されています。

  • atoms: 複数の分子で構成されるコンポーネントであり、再利用性が非常に高いもの。
  • molecules: 複数のアトムで構成されるコンポーネントであり、機能単位で再利用されるもの。
  • organisms: 複数の分子と有機体で構成されるコンポーネントであり、単一のページに関連するもの。
  • templates: レイアウトのような再利用可能なコンポーネントであり、ページ全体のデザインを管理するもの。
  • pages: 各ページに対応するコンポーネントであり、ページの URL に対応しています。

コンポーネントの作成

各ディレクトリにコンポーネントを作成します。例えば、atoms/Button/index.tsx は以下のようになります。

import React from 'react'
import * as S from './styles'

interface Props {
  children: React.ReactNode
  onClick?: () => void
}

const Button = ({ children, onClick }: Props) => {
  return <S.Button onClick={onClick}>{children}</S.Button>
}

export default Button

つまり、Atomic Design は、構成要素をシステム的に扱うためのデザインシステムの考え方で、複雑な UI/UX をよりシンプルかつ再利用可能にします。

Next.js で Atomic Design を実践する

次に、Next.js で Atomic Design を実践する方法を見ていきましょう。まずは、Atomic Design の概念をベースに、Next.js での実装方法について解説します。

Atomic Design のパターンを Next.js で使う

Atomic Design で定義されているアトム、分子、有機体などの概念をベースに、Next.js でのディレクトリ構造を決めていきます。以下に、Atomic Design のパターンに合わせたディレクトリ構造を示します。

src/
  atoms/
    Button/
      index.tsx
      styles.ts
  molecules/
    Header/
      index.tsx
      styles.ts
    SearchForm/
      index.tsx
      styles.ts
  organisms/
    HeroSection/
      index.tsx
      styles.ts
    ProductList/
      index.tsx
      styles.ts
  templates/
    DefaultTemplate/
      index.tsx
      styles.ts
    ProductPageTemplate/
      index.tsx
      styles.ts
  pages/
    index.tsx
    about.tsx
    products/
      [slug].tsx

上記のディレクトリ構造は、Atomic Design の概念を反映したものになっています。各ディレクトリには、その名前に合わせたコンポーネントが格納されています。

  • atoms: 複数の分子で構成されるコンポーネントであり、再利用性が非常に高いもの。
  • molecules: 複数のアトムで構成されるコンポーネントであり、機能単位で再利用されるもの。
  • organisms: 複数の分子と有機体で構成されるコンポーネントであり、単一のページに関連するもの。
  • templates: レイアウトのような再利用可能なコンポーネントであり、ページ全体のデザインを管理するもの。
  • pages: 各ページに対応するコンポーネントであり、ページの URL に対応しています。

コンポーネントの作成

各ディレクトリにコンポーネントを作成します。例えば、atoms/Button/index.tsx は以下のようになります。

import React from 'react'
import * as S from './styles'

interface Props {
  children: React.ReactNode
  onClick?: () => void
}

const Button = ({ children, onClick }: Props) => {
  return <S.Button onClick={onClick}>{children}</S.Button>
}

export default Button
// Button.tsx
import styled from '@emotion/styled'

export const Button = styled.button`
  background-color: #4caf50;
  color: white;
  font-size: 1rem;
  border: none;
  border-radius: 0.25rem;
  padding: 0.5rem 1rem;
  cursor: pointer;
  transition: background-color 0.2s ease;

  &:hover {
    background-color: #357a38;
  }
`

上記のように、Button コンポーネントを定義することができます。このように、Styled Components を使用することで、コンポーネントをよりシンプルかつ再利用可能にすることができます。

最後に、以下は Button コンポーネントを使用する例です。

// MyComponent.tsx
import { Button } from './Button'

export const MyComponent = () => {
  return (
    <div>
      <h1>Hello, world!</h1>
      <Button>Click me!</Button>
    </div>
  )
}

上記のように、Button コンポーネントを MyComponent 内で使用することができます。このように、Styled Components を使用することで、見た目を指定するための CSS がコンポーネント内に閉じ込められ、よりシンプルなコードが書けるようになります。