
デジタル庁やSmartHRのものなど、よくレファレンスとして参考にされる有名なデザインシステムのコンポーネントライブラリでは、「コンポーネント」としてすべてのパーツを定義し、あまり細かく階層を分けないケースが多いように思います。
つまり、デザイン観点ではアトミックデザインのようなコンポーネント階層を無理に導入しない方が良いという結論に至っていそうに見えます。このような定義方法はデザインガイドラインの運用上、わかりやすく、管理もしやすいのではないかと思います。
一方で、システムの実装的な観点で見るともう少し再利用性を高めたまとまりの単位が欲しくなってきます。また、「コンポーネント」としてまとめると必然的に各コンポーネントの抽象度が高くなり、ドメインロジックに紐づいた再利用可能コンポーネントの不在という問題を生み出します。
やや出自が異なる2つのデザインシステムについての議論
アトミックデザインは2013年に登場して以降、さまざまな組織で試行錯誤が繰り返され、その導入方法について多くの議論がなされてきました。もともとアトミックデザインのようなコンポーネント運用に関する議論は開発者視点でのものが多く、「Reactコンポーネントとしてボタンを定義した時に、Atomsであるボタンにセマンティックな意味を与えてしまうアイコンはどのように渡すべきなのか?」のようなソフトウェアアーキテクチャ視点での議論が特に活発でした。
そこから数年、デザイナー視点でのデザインシステム議論も盛んになり、むしろこちらではブランド理念を頂点としたブランドガイドラインを各領域にどのように伝播させていくかといった意味でのデザインの"システム"に関する議論が主なものでした。ここではデザインシステムとコンポーネントライブラリの違いも強く意識され、アトミックデザインについてもこのコンポーネントライブラリの構成の一案として認識されています。
とはいえ、デザイナーが具体的な実装方法のイメージがわからない場合アトミックデザインに関する議論に積極的に関わるのはハードルが高く感じられ、コンポーネントライブラリ内でどのような階層を持つのかという議論はデザイナーとエンジニアで分断されてしまったように思うのです。
改めてコンポーネントライブラリの階層について考えてみる
このように議論が分断されると、デザイナーはFigma上で「コンポーネント」のみ定義してレイアウトなどは各ページで自由にやっている間、エンジニアがアトミックデザインを取り入れたディレクトリ階層を運 用しているみたいなこともありそうな気がしています。
デザイナー視点で見ると、この階層を分けないコンポーネント運用について「別にいいじゃん」というのが率直な感想だと思います。
しかし、この階層を分けずに「コンポーネント」としてすべてまとめる運用は、全てのパーツが抽象化された状態での運用となります。すると結局ドメインロジックに合わせた調整は完全に各画面上での設計に委ねられることになり、一貫性のあるデザインをするためにはコンポーネントライブラリ以外の部分での規定が必要となります。多くの場合はここまで手が回らず、コンポーネントは同じものを使っているけどレイアウトが微妙に違う画面が増えていってしまうのではないでしょうか?
こうなると、デザイナー視点でも目指したかったブランドデザインの一貫した運用は叶わなくなってしまいます。この記事では、ドメインロジックを持ったコンポーネントの再利用性を担保するという点を主なゴールとしてコンポーネントライブラリへの階層導入について考えてみます。
ドメインロジックを含むコンポーネント階層
アムステルダムのデジタルプロダクトデザイン会社「Heavyweight」が2017年に提案しているコンポーネント階層がアトミックデザインよりもわかりやすいのでそちらをベースにしています。さすがデザイン会社だけあって、AtomsやMoleculesのような便宜的でシステマティックな命名ではなく、ブランド全体のデザインシステムとの繋ぎこみを意識した「Identity」から始まる階層名がデザイナー目線でもしっくりくるのではないでしょうか?
2017年にHeavyweightがこの階層を提案した時点では、まだデザイントークンなどのトピックは広く認知されていませんでした。当時コンポーネントの階層構造として提案されたこの命名に、より現在のコンテキストに沿った解釈を行なっていきます。
Identity: 今風にいえばデザイントークン
Identityとは、とても秀逸な命名だと思います。
ブランドのデザインシステム全体で考えると、コンポーネントライブラリ階層の最小単位は、その上位概念となるブランドガイドラインとの"繋ぎこみ"が起こる場所です。例えば、ブランドカラーをモバイルアプリというアプリケーションのコンポーネントライブラリ内のカラーとして再定義して繋ぎ込むイメージです。
この階層は、今や広く認知されているデザイントークンの概念と同じものであると考えるとわかりやすいと思います。アトミックデザインではAtomsが最小単位であったためややこしさを生んでいました(後々Ionsと言う名前で導入されましたが)。
Identityで定義されるのは色やテキストサイズ、マージンなどの数値的なものです。プリミティブトークンとセマンティックトークンと言う2つの概念に分けたSmartHRのデザイントークン定義が大変参考になります。
システム開発的には、この階層はコンポーネントではなく設定ファイルやCSSで定義する部分となります(tailwind.config.jsが一番イメージしやすいかもしれません)。
Elements: いわゆるAtoms
ここが形を持つコンポーネントとしての最小単位です。アトミックデザインでは、Atomsとして定義されていた部分ですね。ボタンやインプットフィールドなどのそれ以上分解できない最小単位です。また、この階層のコンポーネントは抽象的である必要があります。つまり、特定のドメインロジックに紐づいてはいけません。
分解できないと言うと議論が巻き起こるのが、アイコンがついたボタンなどです。ボタンとアイコンに分解できるではないかと。そこはこう考えると良いのではないでしょうか?
アイコンにはコンポーネントに文脈や意味を与える「セマンティックなアイコン」と、操作をアシストする「補助的なアイコン」の2種類があります。ドメインロジックを表現することとなるセマンティックなアイコンはテキストと同じ扱いです。この階層でのコンポーネントの定義上はダミーを置いておけば良いのです。
Components: 一つの機能として成立するが抽象的・汎用的 なコンポーネント
この階層の名前はComponents以外あり得ないのではないでしょうか?さすがにこれをMoleculesと呼ぶのは慣れないです... 一般的にコンポーネントと聞いて思い浮かべるものはすべてここに入ります。いくつかのElementsを包有し、ポップアップやアラートといった情報の伝達やユーザーアクションを完結させることができるコンポーネント単位です。
この階層のコンポーネントもまだドメインロジックを持たない抽象的なものである必要があります。再利用可能なコンポーネントライブラリとして定義することによってデザイナーが実務上のメリットを感じられる階層はここまでかもしれません。
Compositions: マイクロレイアウトを定義し、内部的なドメインロジックを流し込んだもの
前述した通り、デザイナー視点では不要と感じ始める階層です。
Figmaのページ名をアトミックデザインに沿って分けてみたものの、AtomsとMoleculesしか作れなかった(それ以上は運用が大変だし、再利用回数も少ないのでいらないと感じた)というケースは多いのでは?
しかし、この階層の不在は意外とプロダクトの一貫性に関する問題を生み出します。
例えばフォーム一つとってもプロダクト内にはさまざまなユースケースがあります。ユーザー登録フォームではボタンを中央に配置したいが、サーベイ画面では右下に「次へ」と表示したいなど。このユーザー登録やサーベイはドメインロジックに紐づいたものとなります。「コンポーネント」以外の階層を設けない場合、このようなコンポーネントの組み合わせ方は各画面の設計時に検討されます。
つまり、Composition階層ではプロダクトのドメインロジックを持ったコンポーネントを定義することで、このようなユースケ ース別のコンポーネントの使い方を明確に定義できるのです。
Composition階層では、それぞれのボタンラベルやプレースホルダーについても「登録」や「購入」などの各ユースケースに合わせた文言を表示することができるようになります。Elementsでは空白にしておいたセマンティックなボタンアイコンもここで具体的なものを入れ込むことができます。
Layouts: グリッドレイアウトやタイル、リストなど
ここまでは、アトミックデザインの階層名を変えただけのようなものでした。しかし、Layoutsに関してはHeavyweightが提唱したオリジナルの概念です。そして、これが開発者視点でこのコンポーネントライブラリを使いやすいものにしてくれます。
Layoutsとは、他のコンポーネントを組み合わせて作るものではなく、その名の通りページのレイアウトの定義です。ちょっと細かいWeb開 発のコンポーネント設計の話になってしまいますが、例えばガターが20px、マージンが24pxの4カラムグリッドをReact.jsで作ると以下のようになります。
import React from "react";
import cx from "classnames";
function Grid({ children }) {
return <div className="grid grid-cols-4 gap-5 px-6">{children}</div>;
}
export default Grid;
つまりグリッドレイアウトというと、それだけでは具体的な見た目を持たない概念的な存在のようなイメージを持たれますが、コード上では一つのコンポーネントになるのです。これをいくつかコンポーネントとして定義して再利用するというのがレイアウトの一貫性を保つために重要なポイントになります。
Pages / Screens: ダイナミックなコンテキストを渡されたもの
Pages(Screens)はプロダクトの各スクリーンに対応するもので、最終的にデザイナーがつくる画面デザインと一致したものとなります。この階層において重要となるのは、ここで初めてそれぞれのコンポーネントにデータが流し込まれるという点です。
ここまで、ドメインロジックを含んだCompositionsも含めてデータベースから取得したダイナミックなデータをコンポーネント上に表示することはありませんでした。具体的なデータとは、リストに表示される商品情報やログインしているユーザーの情報です。デザイナー視点では、この画面をデザインする際にはダミーデータを使うことをやめて、できるだけリアルなプロトタイプ的デザインを作っていくと良さそうです。
まとめ
もちろん、どのような構造を取り入れても運用上の試行錯誤は生まれるわけですが、最近はアトミックデザイン的な階層構造の導入が見送られるケースがやや多くなっているようです。しかし、階層構造を持つコンポーネントライブラリのメリットはデザイナー視点でも無視し難いものであり、アトミックデザイン的な階層構造の導入について、運用可能性やより良い定義など再度考えてみても良いのではないでしょ うか?