ハコヅミを作る #11:「森」の配色で、画面を作り直す

前回(#10)でMVPを振り返り、次にやることの1つに「UIの見直し」を挙げました。 今回は、その最初の一歩として、画面の土台を作り直しました。

これまでの画面は、機能を確かめるための最低限の見た目で、ページごとに bg-emerald-700 のような色を直接書いていました。これを、サービス全体で決めた方針に沿って置き換えます。


先に、共通の方針を決めた

いきなりハコヅミの画面を直し始めるのではなく、先に「どのサービスでも、色とCSSをどう管理するか」を決めました。 デザイントークン・UI部品・最小限の共通クラスの3段構えで、サービスごとに変えるのはトークンの値だけ、というものです。

中身は、別の記事にまとめました。

この方針は、リポジトリの CLAUDE.md と、Notionの「サービス開発の共通方針」にも書きました。Issueも「方針を書く(#42)」と「ハコヅミの画面を置き換える(#44)」の2つに分けています。 今回の記事は、後者の、ハコヅミでの実践編です。


配色は「森」

トークンの値、つまりハコヅミらしい色を決めました。 Claude Codeに、キャンプアプリに合いそうな配色をいくつか出してもらい、その中から「森」を選びました。

トークン 色 使うところ
primary 深い緑 #2f5d4a ヘッダー、見出し、ボタン、チェックボックス
primary-soft 淡い緑 #dce8df 進み具合のバッジなど
accent 焚き火のオレンジ #c0622b 差し色(まだ使っていない)
surface 生成り #f6f3ea ページの背景
surface-raised 白 カード
ink / ink-muted 墨色 / 灰色がかった茶 文字 / 補足の文字

深い緑はテントやタープ、生成りは帆布、オレンジは焚き火のイメージです。 オレンジの accent は、定義だけして、まだどこにも使っていません。「チェックが全部終わったとき」などの使いどころを、あとで決めるつもりです。

フォントは、当面は端末に入っているもの(システムフォント)のままにしました。


見た目:前と後

チェックリストの画面です。

見直し前のチェックリストの画面。白い背景に黒い文字、チェックボックスは青

前:白い背景に黒い文字。チェックボックスはブラウザ標準の青

見直し後のチェックリストの画面。上部に緑のヘッダー、生成りの背景に白いカード、見出しとチェックボックスが緑

後:上部にヘッダー、生成りの背景に白いカード。見出し・線・チェックボックスが緑になった

画面は、それぞれの時点のコードを手元で動かして撮ったものです。データは#7でNotionから取り込んだ、実際のギアを入れています。

ギアの登録画面です。

見直し前のギアの登録画面。黒い枠の入力欄と、明るい緑の保存ボタン

前:入力欄は黒い枠、保存ボタンは Tailwind の emerald

見直し後のギアの登録画面。白いカードの中に、淡い枠の入力欄と、深い緑の保存ボタン、枠付きのキャンセルボタン

後:カードの中に入力欄をまとめ、キャンセルもボタンの形にした

大きく変わったのは次の点です。

  • 画面の上部に、共通のヘッダーを置いた。アプリ名と、チェックリスト・ギア・コンテナ・プランへのリンクが並び、どの画面からでも移れる
  • 背景を生成りにして、中身を白いカードに載せた
  • 見出しを緑にして、コンテナなどのまとまりの見出しには緑の線を引いた
  • チェックボックスは、ブラウザ標準の形のまま、色だけ緑に合わせた(CSSの accent-color)

画面のコードは、こう変わった

ギアの登録画面のボタンの部分です。前は、色も形もその場に書いていました。

<button type="submit" class="rounded bg-emerald-700 px-4 py-2 text-white">保存</button>
<a href={resolve('/gears')} class="px-4 py-2">キャンセル</a>

後は、UI部品を使うだけです。

<Button type="submit">保存</Button>
<LinkButton href={resolve('/gears')} variant="secondary">キャンセル</LinkButton>

色や角丸は Button の中にしかないので、画面のほうは「何のボタンか」だけが読み取れます。 トップ、ギア、コンテナ、プラン、チェックリストの全画面(13画面)を、この形に置き換えました。


動きは変えない:E2Eをそのまま通す

今回のIssueで一番気をつけたのは、「見た目以外(動き・URL・データ)は変えない」ことです。ACにも、次の1行を入れました。

これまでの E2E テストが、すべてそのまま通る(動きが変わっていない)

ほぼ全画面のファイルを書き換える大きな変更なので、動きが変わっていないことを、人の目だけで確かめるのは無理があります。そこで、これまでに書いてきたE2Eテスト(51件)を、テストのほうは1行も変えずに全部通すことを条件にしました。

これが効いたのが、ヘッダーの作り方です。 E2Eテストは、「見出し(h2)が『カーゴ 30L-1』の section」や「リストの項目」のように、画面の構造を手がかりに要素を探しています。ヘッダーのリンクを見出しやリストの項目で作ると、テストが別の要素を拾ってしまうおそれがありました。 そのため、ヘッダーは見出しもリストも使わず、リンクを並べるだけの作りにしています。


「色が1か所で変わる」ことも、テストで確かめた

もう1つ、今回ならではのACがありました。

app.css の primary の値を変えると、ボタン・見出し・チェックボックスなどの色がまとめて変わる

画面を触っても確かめにくいので、「(自動テストで確認)」としたACです。E2Eテストで、ページに --color-primary だけを差し替えるスタイルを足し、ボタンの背景、見出しの文字、ヘッダーの背景、チェックボックスの色が、4つとも新しい色に変わることを確かめています。

// app.css のトークン(--color-primary)だけを差し替える
await page.addStyleTag({ content: ':root { --color-primary: rgb(200, 30, 60); }' });

どこかの画面に bg-emerald-700 が残っていたり、部品が色を直接持っていたりすると、このテストで見つかります。


パレットの色を書くと、CIが止める

共通方針の記事で書いたとおり、ページに bg-emerald-700 や text-gray-600 のようなパレットの色を直接書くと、CIが失敗するようにしました。

見直しの前は、15ほどのファイルにパレットの色が書かれていました。置き換えたあとは0件です。 実際に、ある画面の text-ink-muted を text-gray-600 に書き換えて、チェックが失敗することも確かめてから、元に戻しました。


Issueからの変更

実装してみて、Issueから2点を変えました。どちらもPRとIssueの「変更履歴」に理由を残しています。

  • 文字と線のトークン名:Issueでは text・border としていましたが、クラス名が text-text・border-border になって読みにくいので、ink・line にした
  • UI部品を2つ追加:Issueに挙げた8つに、メモ用の複数行の入力欄(TextArea)と、白い面(Card)を足した

おわりに

  • 先にサービス共通の方針を決めてから、ハコヅミの画面に当てはめた
  • 配色は「森」。深い緑・生成り・焚き火のオレンジ
  • 動きを変えていないことは、既存のE2Eを変えずに全部通すことで確かめた
  • 色が1か所で変わること、パレットの色を書くと止まることも、テストとCIで確かめた

これで、見た目を直したいときは、トークンかUI部品の1か所を直せば済むようになりました。 ただ、今回は「土台」までです。スマホで片手で操作しやすい大きなボタンなど、積み込みの現場での使いやすさは、まだこれからです。

← トップページに戻る