🎨

iOS デザイントークンを用いてカラーを扱うベストプラクティス

2023/05/16に公開

アプリでカラーを扱う方法で一番私がしっくり来たものを紹介します。
(と言いつつ、まだデザインシステム勉強中なのでアップデートがあるかもしれません。)
デザイントークンを採用しカラーの定義を見直したことで、直感的に実装できレビューにも良い効果があったためそちらの話も書こうと思います。
ダークモードへの対応を予定している方や、カラーの定義や扱い方を再考したい方の参考になれば嬉しいです。

デザインシステムとデザイントークン

エンジニアリングの部分をメインとするため、この辺りは簡単に書きます。私もまだ勉強途中です。

デザインシステム

デザインの原則や方針、UIパターンやライブラリなどを構造化したものです。デザインとコーディングで共通言語を用いることで、低コストで一貫性のあるデザインを実現することを目的としています。

ここで一つ疑問が浮かびます。
iOSやAndroidなどのモバイルネイティブはAppleやGoogleからデザインについてのガイドラインが出ています。

  • Apple: Human Interface Guideline
  • Google: Material Design

ガイドラインが出ているのに、デザインシステムを作ることは有効でしょうか?答えはYesです。
その理由の片鱗はこの後のカラー定義の見直しの実例を見てもらえたら感じていただけると思います。

デザイントークン

デザイントークンとはデザインシステムで最小単位のスタイルを定義するものです。

グローバルトークン


デザイントークンを用いたカラーの表現 出典:Adobe

文脈を問わない名前で表現されます。カラーパレット・タイポグラフィ・アニメーションなどはグローバルトークンとして定義されます。図のblue400がそれに当たります。
これらは直接使用することができ、他のトークンで参照されます。

エイリアストークン


デザイントークンを用いたカラーの表現 出典:Adobe

特定の文脈や抽象的な表現で定義され、複数の場所で用いられる場合に有効です。図のcta-background-colorがそれに当たります。
そのトークンが何に用いられるのかトークンから読み取ることができます。例だとcatの背景色の色だとわかります。

固有トークン


デザイントークンを用いたカラーの表現 出典:Adobe

名前の通り、コンポーネントに対して固有に定義されます。図のbutton-cta-background-colorがそれに当たります。
エンジニアがコンポーネント開発のトークン適用で可能な限り特定できる定義になっています。

実装でのカラーの扱い方

カラーのアセットカタログを作成する

Asset Catalogを新規作成します。名前はColorで良いでしょう。

アセットカタログの左下のプラスボタンからColor Setを選択するとカラーを追加できます。

ダークモードとライトモードで色を変えたい場合は右側のメニューでAppearancesを変更してください。

アセットカタログの値を参照するには通常だとStringで名前を指定しますが、R.swiftを導入していることも多いかと思います。

  • UIColor(named: "")
  • Color("")
  • R.color.xx

Color/UIColorのExtensionを作成する

上記のカラーの参照をカラーを設定するすべての場所で記載しても良いですが、懸念点があります。

文字列で参照する場合は、文字列の間違いや名前の変更が行われた際にバグを生む可能性があります。特にxibが存在するプロジェクトは要注意で、xibで色を設定している場合エラーが出ませんので気が付く可能性が低いです。

Rで参照する場合は大きな問題はないですが、毎回R.color...と書くのは少し億劫です。簡単に参照できるようExtensionを作るのもおすすめです。

// 例: Text-BaseのExtension
extension Color {
  public struct text {
    public static let base: Color = .init(R.color.body.base()!)
  }
}

extension UIColor {
  public struct text {
    public static let base: UIColor = R.color.body.base()!
  }
}

参照する時はこのように指定することができます。

Text("Test")
  .foregroundColor(.text.base)

デザイントークンを取り入れてよかったこと

1. レビューや実装のしやすさが向上

エイリアストークン・固有トークンは何にしようされるべきか命名からわかるようになっています。
そのため実装も分かりやすく、レビューもしやすくなりました。

例えばTextの色を設定している実装です。

Text("Test")
  .foregroundColor(.text.base)

カラーは.text.baseが設定されており、これを見ただけで大きな間違いがないことがわかります。

この箇所が.border.baseになっていたら、おかしいと思いますよね。

Text("Test")
  .foregroundColor(.border.base)

2. デザイナーとのやりとりがスムーズになる

トークンという共通言語で話せることで、デザイナーとの会話がスムーズになりました。

色の確認をしたい箇所も、今までだったら「ここの色どうしますか?」のような会話から始まっていたのが、「.text.baseでいいですか?」と質問できるようになりました。
これは思ったよりもコストを減らしてくれているなと感じます。

上記2つとも冒頭で話したデザインシステム導入の目的に沿っています。

デザインとコーディングで共通言語を用いることで、低コストで一貫性のあるデザインを実現することを目的としています

おわりに

今回はカラーのデザイントークンとその実装についてでした。
デザインシステムはまだ色んな観点が存在します。モバイルアプリで運用するにあたってどのような形が良いか、勉強しながら整理してまた別記事で上げれたらと思います。

Discussion