クロンのデザインシステムを作っている話
この記事は MICIN Advent Calendar 2023 の2日目の記事です。
前回はmanimotoさんの「組織の異動や退場 または私は如何にして心配するのを止めてGoogleグループを削除するようになったか」でした。
私は株式会社MICINのオンライン医療事業部でフロントエンドエンジニアをしているdoutoriと申します。
弊社で提供しているサービス、クロンのデザインシステムを現在進行形で作っています。
クロンのサービスブランド
クロンのブランドとしては主に「オンライン診療クロン」「クロンお薬サポート」「クロンスマートパス」の3軸でサービスを展開しています。
これらに対して、医療機関向け・薬局向け・患者向け・管理者向けと必要に応じた数のサービスを日々開発しています。
デザインシステムを作るに至ったわけ
それぞれのサービスに対して独立した体制で開発を進めてはいるのですが、開発頻度はサービスに依りまちまちで、また横断的・継続的に開発プロセスを見ている人材が存在しておらず、独自に定義されていたUIデザインやコンポーネントが入り乱れていました。
顧客に提供されているUIが一貫性のないものになりつつあり、サービス全体をクロンブランドとして展開していく際に障害となりうる懸念が出てきたため、デザインシステムを構築することにしました。
デザインシステムを立ち上げる
ちょうど時期的にこのデザインシステムを構築する話が浮上する前から、クロンお薬サポートのリニューアルのプロジェクトが走っており、デザインシステムの設計・構築は、リニューアルのプロジェクトと並行して進めることとなりました。
お薬サポートのリニューアルの構成は、デザインシステムを見越してモノレポの構成にしていたので、汎用的なコンポーネントやロジックはpackages配下に独立させていました。
いつか来たるべき日に...と思っていたものが、結果として功を奏した形となりました。
project
- apps
- ...
- packages
- curon-icons # 主にアイコンのコンポーネントのみ
- curon-ui # 汎用的なコンポーネントのセット
- curon-ui-theme # デザイン原則に沿った、カラースキーマなどのスタイルガイドの設定
- ...
エンジニア側ではこれらをもとに、デザインシステム側に移植できる部分は移植していきつつ、デザイナ側ではデザイントークンの設計を進めてもらいました。
デザイントークンの選定
カラースキーマについてですが、クロンブランドのイメージに沿ったカラーリングを抽出するとともに、WCAGにて定義されているコントラストのAA基準を満たせるかどうかも指針の1つとしています。
curon のデザイントークンからカラーパレットの抜粋
スペーシングについては、既存サービスからよく利用されている余白を抽出し定義していっています。
curon のデザイントークンからスペーシングの抜粋
このほかにもTypographyなどUIデザインを構築、実装する上で必要な要素はすべてFigmaのTokenとして管理されており、デザイナ・エンジニア間での共通認識となっています。
アイコンのコンポーネント化
Figmaに定義されているアイコングラフィをFigmaAPIを利用してsvgファイルとして取得します。
const getComponentNode = (nodes) => {
if (!nodes.children) return
return nodes.children.flatMap((c, index) => {
if (c.type === "COMPONENT") return { id: c.id, name: c.name }
return c.children ? getComponentNode(c) : []
})
}
const main = async () => {
const response = await fetch(
`https://api.figma.com/v1/files/${FILE_KEY}/nodes?ids=${FIGMA_ICONS_NODE_ID}`,
{
headers: { "X-FIGMA-TOKEN": TOKEN },
},
)
const { nodes } = await response.json()
const results = getComponentNode(nodes[FIGMA_ICONS_NODE_ID].document)
const ids = results.map((r) => r.id).join(",")
const svgResponse = await fetch(
`https://api.figma.com/v1/images/${FILE_KEY}?ids=${ids}&format=svg`,
{
headers: { "X-FIGMA-TOKEN": TOKEN },
},
)
const { images } = await svgResponse.json()
const nodeIds = Object.keys(images)
for (const nodeId of nodeIds) {
const url = images[nodeId]
const result = results.find((r) => r.id === nodeId)
const name = result.name
const path = resolve(__dirname, `../assets/${name}-icon.svg`)
download(url, path, () => {
console.log(path, "done!")
})
}
}
Figmaファイルからsvgアイコンを取得するロジックはUbieさんの実装[1]を参考にしています。
※Figmaファイルの構成が若干異なるため、一部手を加えている形です。
取得したsvgファイルをsvgrを利用してReactコンポーネント化しています。
UIコンポーネントの実装
クロンの一部サービスがChakraUIを利用していたので、UIコンポーネント実装のベータ版としては、そのままChakraUIを踏襲する形で実装を進めました。
現状の構成ですとどうしてもCSSinJSライブラリのemotionのRuntimeがのってきてしまうのですが、現状としては良しとしています。
ChakraUIでは基本のテーマが提供されていますが拡張することができるので、ベースとなるコンポーネントについてはテーマに手を入れることで実装をしています。
Form周りで利用するコンポーネントを優先的に、現在では14種類のコンポーネントが提供されています。
curonのUIコンポーネントからボタンコンポーネントの抜粋
また、パッケージとして配布しているクロンのUIコンポーネントライブラリには、クロン用に拡張したテーマを含んだThemeProviderも提供しています。
アプリケーション側とパッケージ側でThemeProviderが分かれてしまっていると、共通のスタイルを充てることができなかった[2]ので、このような形をとっています。
デザインシステムの運用について
デザインシステムのプロジェクトが始まってから現在に至るまで、ほぼ週一ペースでデザイナと意見交換を続けています。
基本的にはその場で課題や提案を行い、採用されたものは実装され、Storybookなどでレビューを経たものがデザインシステムに組み込まれていきます。
さいごに
今回作っているデザインシステムはまだまだ発展途上で、開発チームからの要望を全て満たせているわけではありません。
ただ、職種に関係なく、クロンのUIや顧客体験がどうあるべきかの深い議論ができるようになってきたと感じています。
クロンのサービスをデザインシステムも含めて育てていくものという共通理念をもとに、今後とも価値提供を最大限発揮するために日々開発を続けていきたいです。
MICINではメンバーを大募集しています。
「とりあえず話を聞いてみたい」でも大歓迎ですので、お気軽にご応募ください!
-
https://github.com/ubie-oss/ubie-icons/blob/main/scripts/figma.js ↩︎
-
依存する@chakra-ui/reactのバージョンも揃える必要があります。 ↩︎
Discussion