跳至主要内容
💬 回報這一頁

ADR-0007:主題色相只進識別層——動作、互動、聚焦一律中性

  • 狀態:已採用
  • 日期:2026-07

背景

多色相主題(v0.3.0 起)讓宿主用 data-color-theme 換一套色相。從那天起, 「主題色相可以出現在哪些介面層」這個問題被重新討論了三次,每次都要重新考古量測數據:

  1. v0.3.0--primary--brand 分家——品牌色偏亮偏飽和,直接當 primary 會讓高飽和色的出現面積失控。同一輪把 --ring 從中性改成吃主題色相
  2. v0.6.0:石墨(預設主題)照公式生成的近中性 brand,距離「停用」的外觀只有 ΔE00 8.5——brand 按鈕看起來像停用的。修法是承認預設主題沒有品牌色(鏡射 primary), 並加守衛 ΔE00(brand, 停用外觀) ≥ 12
  3. 本次:實際使用發現主題色聚焦環會與欄位提醒色撞在同一個輸入框上—— 一格「已改動未送出」的琥珀欄位獲得焦點時,琥珀(語意)與主題紫(焦點) 兩套強調色疊在一起;切到青玉主題又變成琥珀配青綠。同一個畫面元素上的 強調色組合隨主題漂移,聚焦環的用意會被誤讀成另一種提醒。

三次討論、零份正本。這則 ADR 把色相預算一次寫死。

選項

選項說明
A. 主題色相可以進元件(ring 維持主題色、brand 按鈕不設限)識別感最強,但強調色組合隨主題變,與提醒色的碰撞無法根治
B. 主題色相只進識別層;聚焦環改回中性;brand 按鈕維持有守衛的邊界提醒色的語意空間完全獨立於主題;識別集中在 Layout
C. 元件層完全零主題(收掉 brand variant、表面不帶色調)規則最簡單,但表面純灰與帶色 Layout 並置會產生「兩套系統拼裝」感(v0.6.0 實測),且識別無處落腳

決定

採 B。 色相預算如下:

介面層吃主題色相?載體
Layout 大區塊背景風格色調✅(只轉色相)12 個帶色調中性色(--background--card--muted--border…,chroma 0.007–0.023)
選單/選中導覽項/品牌強調--brand 家族 4 個(brandbrand-foregroundbrand-subtlebrand-subtle-foreground
動作(按鈕)--primary 中性近黑;唯一例外是 Buttonbrand variant(見下)
互動(hover/pressed/已選)currentColor 疊加(6%/14%/20%),機制本身無色相
聚焦環❌(本次改回)--ring 回落 :root 中性基礎值,主題層不再覆蓋
狀態/提醒色successwarninginfodangerdestructiveedit 全主題不變
資料(圖表 8 色)全主題共用

主題覆蓋的 token 從 17 個減為 16 個(brand 4 + 帶色調中性 12)。

Buttonbrand variant 是有守衛的邊界例外:只給一頁一顆的非提交型入口, 確認/送出/儲存一律 primary,且守衛盯著 ΔE00(brand, 停用外觀) ≥ 12。 它屬於識別層(「這是誰的產品」),不屬於動作層。

理由

  1. 提醒色與焦點指示是兩個體系,不能共享色相空間。 欄位提醒色(琥珀=已改動、danger=有問題)與聚焦環會出現在同一個輸入框上。 ring 帶主題色相時,這個組合每換一次主題就變一次;ring 中性之後, 「語意用彩色、焦點用中性」在所有主題下恆成立——色彩語言統一,切主題不會誤讀。
  2. 色彩疲勞管的是面積 × 頻率,這把尺對 ring 與按鈕給出相反的答案。 按鈕面積大、頻率高,主題色進去會讓換主題等於換整個介面的吵度——所以 primary 必須中性。 聚焦環 2px 寬、一次只有一個,主題色在它身上換不到多少識別價值, 卻要付出與提醒色撞色的成本。付出與收益都指向中性。
  3. 無障礙在這個決定上是中立的,所以不構成反對理由。 聚焦環的門檻是對最亮表面 3:1(WCAG 1.4.11/2.4.7),靠的是亮度差不是色相—— 色覺障礙使用者辨識 ring 從來不靠顏色。中性 ring 對六主題表面實測 20.01:1(淺)/8.54–8.76:1(深),全部遠超門檻。
  4. 表面帶色調是「主題在 Layout、元件冷靜」能成立的前提,不是違例。 v0.6.0 實測:主色暖綠而表面固定冷藍時,介面有「兩套系統拼裝」感。 表面 token 由 Layout 與元件共用,chroma 壓在 0.023 以下、只轉色相、 L 與對比關係不動——單格不可辨,但讓帶色的 Layout 與中性的元件坐在同一個世界。

影響

  • generate-theme.mjs 不再為主題生成 ringverify-color.mjs 改驗 「中性基礎 ring 對每個主題最亮表面 3:1」(同一個 ring、六個對象,逐主題驗)。
  • 主題宿主的聚焦環外觀改變(主題色 → 中性)。@dooping/tokens bump minor。
  • 元件零行為改動——全部走 ring-ring,值的決定在 token 層。
  • 想要「元件連 brand 都沒有」的全中性姿態:用石墨主題,不是改 token。
  • 想在確認按鈕上用主題色、或想讓 ring 吃主題色:必須先推翻這則 ADR。
  • 每個提醒色的定義、場景與擴充程序見文件站「提醒色辭典」; 色相預算的速查表在「深淺主題 → 色相預算」。