【AtomicDesign】学習メモ

コンポーネント指向なフレームワーク（Vue, React, Angularなど）でフロントエンドを実装する際、どのレベルでコンポーネントを分ければ良いのか悩むことがよくあります...。その際に参考となるものが欲しかったので、UIデザインシステムの代表例でもあるAtomicDesignを最近学習しました。自分なりの理解/実装方法を備忘録として記事にしましたので、同志のお役に立てると幸いです。あくまで個人的にしっくりきた考えのもと作成した記事ですので、ご了承ください❗️

## AtomicDesignとは
Webデザイナーの[Brad Frost](https://bradfrost.com/)氏によって提唱されたデザインシステムです。
「小さい要素を組み合わせることでUIを作成していこう」という考え方でUIを構築するのが特徴です。小さい単位でコンポーネントをたくさん用意していおいて、必要なところで随時利用するという流れで実装していきます。これにより、再利用可能でメンテナンス性の高い実装をすることができます。アトミックデザイン、なんか必殺技みたいでかっこいいですよね。

## AtomicDesignを構成する5つのパーツ
AtomicDesignの最大の特徴として、5つのパーツが用意されます。
小さい単位から順に、`Atoms`、`Molecules`、`Organisms`、`Templates`、`Pages`と呼ばれます。それぞれの単位は基本的に、その単位よりレベルの低い単位を構成して作られます。

![Screen Shot 2023-03-28 at 13.10.49.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2356280/31cb7ee9-de4e-adbc-46fe-2c109ea7601d.png)
※出典：[Atomic Design by Brad Frost](https://atomicdesign.bradfrost.com/)

以下では、それぞれのレベルの定義と、実装する際に気を付けるポイントを自分なりにまとめました。
### Atoms（原子）
**AtomicDesignにおける最小単位**です。ボタン、アイコン、リンクなどの「それ以上分解できないもの」が`Atoms`にあたります。

`Atoms`を実装する上で意識するポイントは以下です。
- 1つのタグのみで完結する（`a`,`input`,`button`, `p`など）
- 特定の文言を表示しない（UIの知識を保持しない）
- APIは実行しない（アプリケーションの知識を保持しない）
- 表示したい文言や、指定する属性などは`props`で受け取り、汎用性の高いものにする
- `props`を利用して親からデータを受け取る
- `emit`を利用して親のイベントを発火する

### Molecules（分子）
**Atomの組み合わせによって意味を持つ要素**です。

`Molecules`を実装する上で意識するポイントは以下です。
- `Atoms`を組み合わせて意味を成す最小限の集合（入力フォームと、エラーメッセージが表示される領域のセットなど）
- 特定の文言を表示してもよい（UIの知識を保持してもよい）
- APIは実行しない（アプリケーションの知識を保持しない）
- 一応機能するが、単体では成立しない
- `props`を利用して親からデータを受け取る
- `emit`を利用して親のイベントを発火する

### Organisms（有機体）
**`Atoms`または`Molecules`の組み合わせよって作成されたヤツ**です。

`Organisms`を実装する上で意識するポイントは以下です。
- 特定の文言を表示してもよい（UIの知識を保持してもよい）
- APIを実行をしてもよい（アプリケーションの知識を保持してもよい）
- それ単体で機能する / そのまま別のTemplateに置くだけでも成立する
- `props`は基本書かない：単体で成立させる為


### Templates（テンプレート）
**`Organisms`の位置を定義したワイヤーフレームみたいなヤツ**です。

`Templates`を実装する上で意識するポイントは以下です。
- `Organism`、`Molecules`、`Atom`を組み合わせてページの見た目を作成する
- これを見ただけでどんな感じのページなのかが分かる必要がある
- 特定の文言を表示てもよい（UIの知識を保持してもよい）
- APIを実行をしてもよい（アプリケーションの知識を保持してもよい）
- 画面毎に`Templates`を用意して、ルーティングではコレを出し分ける（人によって異なるのですが僕はコレがやりやすいと思います）
- 基本的に`Molecules`と`Atoms`は使わない

### Pages（ページ）
AtomicDesignでのUI開発における最終形態で、実際にユーザーに表示される画面です。`Templates`との違いは、実際に表示される画像やユーザー毎のデータが表示されているかどうかの違いです。個人的には、`Templates`と`Pages`は大体同じものという認識でもよさそうな気がします。実装を分ける必要もあまり無いと思います。

## AtomicDesignを採用するメリット・デメリット

### メリット
- 作成したコンポーネントを、別アプリで同様のレイアウトを作成する際に再利用することができる
- それぞれのコンポーネントの役割が明確になる
- メンテナンスしやすい
    - 複数画面で使用されている小さい要素に対して修正が入った際に、修正箇所が縮小される（ボタンの色修正とか）
- 一貫性の向上
    - チーム全体で共通の考えの元コンポーネント分割ができることによる

### デメリット
- 実装が難しい
    - 汎用性を持たせるのは難易度が高い
    - AtomicDesignの考え方のズレが生まれやすいので、どの粒度で分けるかで混乱を生みやすい。「このプロジェクトではこれでいこう！」などの認識の共有が必要

## 実装例（Vue.js）
AtomicDesignな実装を取り入れたプロジェクトでの経験と、AtomicDesignを学習して学んだことを元にVue3でシンプルな画面を実装してみました。CSSフレームワークにはTailwindCSSを使用しています（Tailwind...?という方は[こちらの記事](https://qiita.com/whopper1962/items/655cdf1b0718eb733466)でTailwindについて紹介していますので、是非ご覧ください！）。
コードは[こちらのリポジトリ](https://github.com/whopper1962/atomic-design-tutorial)に格納されています。
探り探りの実装なので、「この方が良くない...?」等ありましたら、是非コメントお願いします❗️
![Screen Shot 2023-04-03 at 18.08.27.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2356280/f9700d59-5a57-11c6-2e66-91c9dd5238f8.png)
`src/`配下のディレクトリ構成は以下のようにしました。
~~~bash
src
├── App.vue
├── components
│   ├── atoms
│   │   ├── AtomButton.vue
│   │   ├── AtomImage.vue
│   │   ├── AtomLink.vue
│   │   ├── AtomText.vue
│   │   └── AtomTitle.vue
│   ├── molecules
│   │   ├── MoleculeCard.vue
│   │   ├── MoleculeHeaderLinks.vue
│   │   └── MoleculeHeaderTitle.vue
│   ├── organisms
│   │   ├── OrganismCards.vue
│   │   ├── OrganismFooter.vue
│   │   └── OrganismHeader.vue
│   └── templates
│       └── TemplateHome.vue
~~~

`Atoms`なら`Atom~.vue`、`Molecules`なら`Molecule~.vue`、`Organisms`なら`Organism~.vue`、`Templates`なら`Template~.vue`とった感じでそれぞれのコンポーネントファイル名を付けることが良さそうです。使用される際に、そのコンポーネントがどの単位のものなのかが明確になるのでオススメです（特に`Atoms`と`Molecules`が入り混じる`Organisms`内が見やすくなります）。

最後まで読んでいただきありがとうございました！