07 — Design Tokens
7.1 策略
完全沿用 edge-ai-platform 的 tokens(來源:frontend/src/app/globals.css),僅補 desktop 專用項目。理由:
- 原專案採 shadcn + oklch 中性色盤,已經過調教
- Logo 沿用(決策 Q14),色系一致
- 減少 local 版的設計負擔,聚焦桌面 app 獨有課題
所有 token 來源以下列註記標示:
- [沿用] = 直接從 edge-ai-platform 抄過來,不改
- [新增] = visionA-local 補的 desktop 專用 token
- [微調] = 沿用但數值略改(需說明原因)
7.2 Reference Tokens(原始值)
Colors — Light Mode [沿用]
| Token |
Value (oklch) |
對應原專案變數 |
color.background |
oklch(1 0 0) |
--background |
color.foreground |
oklch(0.145 0 0) |
--foreground |
color.card |
oklch(1 0 0) |
--card |
color.card-foreground |
oklch(0.145 0 0) |
--card-foreground |
color.popover |
oklch(1 0 0) |
--popover |
color.primary |
oklch(0.205 0 0) |
--primary |
color.primary-foreground |
oklch(0.985 0 0) |
--primary-foreground |
color.secondary |
oklch(0.97 0 0) |
--secondary |
color.muted |
oklch(0.97 0 0) |
--muted |
color.muted-foreground |
oklch(0.556 0 0) |
--muted-foreground |
color.accent |
oklch(0.97 0 0) |
--accent |
color.destructive |
oklch(0.577 0.245 27.325) |
--destructive |
color.border |
oklch(0.922 0 0) |
--border |
color.input |
oklch(0.922 0 0) |
--input |
color.ring |
oklch(0.708 0 0) |
--ring |
Colors — Dark Mode [沿用]
| Token |
Value (oklch) |
color.background |
oklch(0.145 0 0) |
color.foreground |
oklch(0.985 0 0) |
color.card |
oklch(0.205 0 0) |
color.primary |
oklch(0.922 0 0) |
color.primary-foreground |
oklch(0.205 0 0) |
color.secondary |
oklch(0.269 0 0) |
color.muted |
oklch(0.269 0 0) |
color.muted-foreground |
oklch(0.708 0 0) |
color.destructive |
oklch(0.704 0.191 22.216) |
color.border |
oklch(1 0 0 / 10%) |
color.input |
oklch(1 0 0 / 15%) |
color.ring |
oklch(0.556 0 0) |
Semantic 擴充 [新增]
以下 semantic token 在原專案沒有明確定義,local 版補齊供狀態顯示用:
| Token |
Light |
Dark |
用途 |
color.success |
oklch(0.65 0.17 145) |
oklch(0.75 0.17 145) |
裝置 Ready、推論成功 |
color.warning |
oklch(0.75 0.18 85) |
oklch(0.80 0.18 85) |
Mock badge、警告訊息 |
color.info |
oklch(0.60 0.15 240) |
oklch(0.70 0.15 240) |
資訊提示 |
color.mock-badge.bg |
oklch(0.88 0.15 85) |
oklch(0.35 0.15 85) |
Mock 模式 badge 背景 |
color.mock-badge.fg |
oklch(0.30 0.18 85) |
oklch(0.92 0.12 85) |
Mock 模式 badge 文字 |
Typography [沿用 + 新增]
| Token |
Value |
備註 |
font.family.sans |
見 06-cross-platform §6.5 |
跨平台 system font stack |
font.family.mono |
見 06-cross-platform §6.5 |
Log viewer |
font.size.xs |
12px |
[沿用] |
font.size.sm |
13px |
[微調] 桌面 app 密度略高於 web,body 從 14 改 13 |
font.size.base |
14px |
[微調] 原 16,桌面常用 14 |
font.size.lg |
16px |
[沿用] |
font.size.xl |
18px |
[沿用] |
font.size.2xl |
22px |
[沿用] |
font.size.3xl |
28px |
[沿用] |
font.size.4xl |
32px |
First-Run welcome |
font.weight.regular |
400 |
|
font.weight.medium |
500 |
|
font.weight.semibold |
600 |
|
font.weight.bold |
700 |
|
font.line-height.tight |
1.2 |
|
font.line-height.normal |
1.5 |
|
font.line-height.relaxed |
1.75 |
|
Spacing [沿用 — tailwind 4 預設]
| Token |
Value |
space.0 |
0 |
space.1 |
4px |
space.2 |
8px |
space.3 |
12px |
space.4 |
16px |
space.5 |
20px |
space.6 |
24px |
space.8 |
32px |
space.10 |
40px |
space.12 |
48px |
space.16 |
64px |
Radius [沿用]
| Token |
Value |
對應原變數 |
radius.sm |
calc(var(--radius) - 4px) = 6px |
--radius-sm |
radius.md |
calc(var(--radius) - 2px) = 8px |
--radius-md |
radius.lg |
var(--radius) = 10px |
--radius-lg |
radius.xl |
calc(var(--radius) + 4px) = 14px |
--radius-xl |
radius.2xl |
calc(var(--radius) + 8px) = 18px |
--radius-2xl |
radius.full |
9999px |
圓形 avatar、pill |
基礎 --radius = 0.625rem (10px)。
Elevation [新增]
桌面 app 需要比 web 更清晰的 z-depth:
| Token |
Light shadow |
Dark shadow |
用途 |
elevation.0 |
none |
none |
Flat |
elevation.1 |
0 1px 2px rgba(0,0,0,0.06) |
0 1px 2px rgba(0,0,0,0.4) |
Card |
elevation.2 |
0 2px 4px rgba(0,0,0,0.08) |
0 2px 4px rgba(0,0,0,0.5) |
Hover card |
elevation.3 |
0 4px 12px rgba(0,0,0,0.10) |
0 4px 12px rgba(0,0,0,0.55) |
Dropdown、popover |
elevation.4 |
0 8px 24px rgba(0,0,0,0.15) |
0 8px 24px rgba(0,0,0,0.65) |
Modal、drawer |
Motion [新增]
| Token |
Value |
用途 |
motion.duration.instant |
100ms |
Micro-feedback |
motion.duration.fast |
150ms |
Button hover、tab switch |
motion.duration.normal |
250ms |
Modal open、drawer slide |
motion.duration.slow |
400ms |
Page transition |
motion.easing.standard |
cubic-bezier(0.4, 0, 0.2, 1) |
預設 |
motion.easing.decelerate |
cubic-bezier(0, 0, 0.2, 1) |
進入動畫 |
motion.easing.accelerate |
cubic-bezier(0.4, 0, 1, 1) |
離開動畫 |
遵守 prefers-reduced-motion:所有 duration > instant 都要在使用者開啟 reduced motion 時改為 0ms 或 instant。
7.3 Component Tokens(重點元件)
| Token |
Value |
sidebar.width.expanded |
240px |
sidebar.width.collapsed |
64px |
sidebar.background |
color.card |
sidebar.border |
1px solid color.border(右邊) |
sidebar.item.height |
44px |
sidebar.item.padding |
space.3 space.4 |
sidebar.item.radius |
radius.md |
sidebar.item.active.bg |
color.primary |
sidebar.item.active.fg |
color.primary-foreground |
sidebar.item.hover.bg |
color.accent |
| Token |
Value |
header.height |
56px |
header.background |
color.background |
header.border |
1px solid color.border(下邊) |
header.padding |
space.4 space.6 |
Card
| Token |
Value |
card.background |
color.card |
card.border |
1px solid color.border |
card.radius |
radius.lg |
card.padding |
space.5 |
card.shadow |
elevation.1 |
card.hover.shadow |
elevation.2 |
Button
| Size |
Height |
Padding |
Font size |
Radius |
sm |
32px |
space.2 space.3 |
font.size.sm |
radius.md |
md |
40px |
space.2 space.4 |
font.size.base |
radius.md |
lg |
48px |
space.3 space.6 |
font.size.lg |
radius.lg |
Variants:primary、secondary、ghost、destructive、outline(沿用 shadcn 定義)。
Mock Badge [新增]
| Token |
Value |
badge.mock.bg |
color.mock-badge.bg |
badge.mock.fg |
color.mock-badge.fg |
badge.mock.padding |
space.1 space.2 |
badge.mock.radius |
radius.full |
badge.mock.font-size |
font.size.xs |
badge.mock.font-weight |
font.weight.semibold |
badge.mock.border |
1px solid currentColor |
7.4 與原專案 tokens 的差異摘要
| 項目 |
改動 |
原因 |
| body font size |
16 → 14 |
桌面 app 資訊密度要求 |
新增 color.success/warning/info |
— |
原專案沒有明確 semantic color |
新增 color.mock-badge.* |
— |
Mock 模式專用視覺 |
新增 elevation.* |
— |
原專案 shadow 只用 tailwind 預設 |
新增 motion.* |
— |
統一動畫語言 |
| 其他 |
完全沿用 |
shadcn 架構已足夠 |
7.5 Token 落地檔案建議
frontend/
├─ src/styles/tokens.css ← 所有 CSS variables
├─ src/styles/globals.css ← import tokens.css
└─ tailwind.config.ts ← extend theme 引用 tokens
沿用原專案的 CSS variable 命名(--primary 等),不做全面改名,以減少沿用原元件的改動成本。
7.6 深色模式切換(第四輪定案)
深色模式的切換完全靠 CSS prefers-color-scheme media query,不需要 JS / Wails emit event。三平台 WebView(macOS WKWebView、Windows WebView2、Linux WebKit2GTK)皆原生支援系統主題即時同步。
實作方式:
/* tokens.css */
:root {
--background: oklch(1 0 0);
/* ...其他 light tokens */
}
@media (prefers-color-scheme: dark) {
:root {
--background: oklch(0.145 0 0);
/* ...其他 dark tokens */
}
}
或用 Tailwind dark: variant(需設定 darkMode: 'media' 而非 'class')。
細節見 06-cross-platform.md §6.8。