Theme / v2.15.0

UI UX Pro Max

把模糊需求變成可實作、可驗收的介面

實戰範例

實戰範例 007:建立真正可用的深色模式

不直接反轉顏色,從語意 Token、元件狀態和系統偏好建立可讀、可恢復的深色模式。

建立真正可用的深色模式

為什麼不能直接反轉顏色?

亮色主題的陰影、灰色文字和邊框在深色背景會失去層次;狀態色太亮又會造成刺眼對比。深色模式是一套新的語意映射,不是 filter: invert(1)

1. 建立兩組 semantic tokens

:root {
  --surface-page: 248 250 252;
  --surface-card: 255 255 255;
  --text-primary: 15 23 42;
  --text-muted: 71 85 105;
  --border-default: 226 232 240;
  --action-primary: 79 70 229;
}

[data-theme='dark'] {
  --surface-page: 15 23 42;
  --surface-card: 30 41 59;
  --text-primary: 241 245 249;
  --text-muted: 148 163 184;
  --border-default: 51 65 85;
  --action-primary: 129 140 248;
}

元件只讀取角色,不讀取 indigo 或 slate 的 raw 值。

2. 處理偏好順序

常見順序是:使用者明確選擇 > 儲存的偏好 > 作業系統偏好 > 預設亮色。初始化時先驗證值,再套用主題;無法使用 localStorage 時仍應正常顯示。

const stored = localStorage.getItem('theme');
const system = matchMedia('(prefers-color-scheme: dark)').matches;
const theme = stored === 'light' || stored === 'dark'
  ? stored
  : system ? 'dark' : 'light';
document.documentElement.dataset.theme = theme;

正式網站需避免 SSR 頁面先用亮色再跳暗色,可在 head 放最小初始化腳本。

3. 逐元件測試

特別檢查 placeholder、disabled、focus ring、錯誤、成功、圖表輔助線和圖片。對比度不是唯一條件;色彩也不能是唯一的狀態訊號。

驗收

  • 系統偏好和使用者偏好不會互相閃爍。
  • 亮暗主題都能完成登入、表單和主要操作。
  • 減少動態偏好仍然有效。
  • 重新整理、無儲存空間和無效主題值都有安全預設。