iOS デザイントークンを用いてカラーを扱うベストプラクティス
アプリでカラーを扱う方法で一番私がしっくり来たものを紹介します。
(と言いつつ、まだデザインシステム勉強中なのでアップデートがあるかもしれません。)
デザイントークンを採用しカラーの定義を見直したことで、直感的に実装できレビューにも良い効果があったためそちらの話も書こうと思います。
ダークモードへの対応を予定している方や、カラーの定義や扱い方を再考したい方の参考になれば嬉しいです。
デザインシステムとデザイントークン
エンジニアリングの部分をメインとするため、この辺りは簡単に書きます。私もまだ勉強途中です。
デザインシステム
デザインの原則や方針、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