visionA/docs/autoflow/03-design/design-tokens.md
jim800121chen fb7da5d180 chore(autoflow): migrate .autoflow/ 共享層文件至 docs/autoflow/
依 autoflow-agent workspace v2 設計把 PRD / 設計 / 架構 / 交付類
共享文件從個人層 .autoflow/(ignored)搬到 docs/autoflow/(進 git),
讓團隊可共享產品與架構文件,個人層只留 progress / review / testing 等
per-branch 筆記。

- 02-prd/        21 個檔(PRD、features、market-analysis 等)
- 03-design/     18 個檔(design-spec、wireframes、flows 等)
- 04-architecture/ 31 個檔(TDD、design-doc、ADR×14、API 規格等)
- 07-delivery/   3 個檔(project-summary、phase-0.6-handover、stage-deployment-setup)

合計 73 檔。原檔已從 .autoflow/ 移除(migration 工具執行 git mv,
但因 .autoflow/ 在 .gitignore 中、git 將此操作視為新增、無 rename history)。
2026-05-04 16:55:55 +08:00

273 lines
12 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Design Tokens — visionA Cloud
> 本文件從 `local-tool/frontend/src/app/globals.css` 反向整理,並確認本專案**完全沿用**既有 Tokens不新增、不覆寫。
>
> 底層採用 Tailwind CSS 4 的 `@theme inline` 機制,以 shadcn/ui 慣例命名 CSS 變數;色彩使用 `oklch()` 色彩空間。Dark Mode 透過 `.dark` class 於 `<html>` 切換,由 `ThemeSync` 元件根據系統偏好設定。
---
## 1. Reference Tokens原始值
### 1.1 色彩 — Light Theme`:root`
| Token | CSS 變數 | oklch 值 | 近似 Hex | 用途 |
|-------|---------|---------|---------|------|
| bg.base | `--background` | `oklch(1 0 0)` | `#FFFFFF` | 頁面背景 |
| fg.base | `--foreground` | `oklch(0.145 0 0)` | `#252525` | 主要文字 |
| surface.card | `--card` | `oklch(1 0 0)` | `#FFFFFF` | Card 背景 |
| surface.card.fg | `--card-foreground` | `oklch(0.145 0 0)` | `#252525` | Card 內文 |
| surface.popover | `--popover` | `oklch(1 0 0)` | `#FFFFFF` | Popover / Dropdown 背景 |
| surface.popover.fg | `--popover-foreground` | `oklch(0.145 0 0)` | `#252525` | Popover 內文 |
| brand.primary | `--primary` | `oklch(0.205 0 0)` | `#343434` | 主要按鈕(近黑,不是傳統藍)|
| brand.primary.fg | `--primary-foreground` | `oklch(0.985 0 0)` | `#FAFAFA` | 主按鈕文字 |
| state.secondary | `--secondary` | `oklch(0.97 0 0)` | `#F7F7F7` | 次要按鈕背景 |
| state.secondary.fg | `--secondary-foreground` | `oklch(0.205 0 0)` | `#343434` | 次要按鈕文字 |
| state.muted | `--muted` | `oklch(0.97 0 0)` | `#F7F7F7` | 禁用 / 非主要背景 |
| state.muted.fg | `--muted-foreground` | `oklch(0.556 0 0)` | `#888888` | 輔助文字 |
| state.accent | `--accent` | `oklch(0.97 0 0)` | `#F7F7F7` | Hover / Active 背景 |
| state.accent.fg | `--accent-foreground` | `oklch(0.205 0 0)` | `#343434` | Accent 上的文字 |
| state.destructive | `--destructive` | `oklch(0.577 0.245 27.325)` | 紅色 | 刪除 / 危險 |
| border.base | `--border` | `oklch(0.922 0 0)` | `#EBEBEB` | 邊框 |
| input.base | `--input` | `oklch(0.922 0 0)` | `#EBEBEB` | Input 邊框 |
| ring.focus | `--ring` | `oklch(0.708 0 0)` | `#B4B4B4` | Focus ring |
| chart.1 | `--chart-1` | `oklch(0.646 0.222 41.116)` | 橘 | 圖表色 1 |
| chart.2 | `--chart-2` | `oklch(0.6 0.118 184.704)` | 青 | 圖表色 2 |
| chart.3 | `--chart-3` | `oklch(0.398 0.07 227.392)` | 深藍 | 圖表色 3 |
| chart.4 | `--chart-4` | `oklch(0.828 0.189 84.429)` | 黃綠 | 圖表色 4 |
| chart.5 | `--chart-5` | `oklch(0.769 0.188 70.08)` | 金 | 圖表色 5 |
| sidebar.bg | `--sidebar` | `oklch(0.985 0 0)` | `#FAFAFA` | Sidebar 背景 |
| sidebar.fg | `--sidebar-foreground` | `oklch(0.145 0 0)` | `#252525` | Sidebar 文字 |
| sidebar.primary | `--sidebar-primary` | `oklch(0.205 0 0)` | `#343434` | Sidebar 主色 |
| sidebar.border | `--sidebar-border` | `oklch(0.922 0 0)` | `#EBEBEB` | Sidebar 分隔線 |
### 1.2 色彩 — Dark Theme`.dark`
| Token | CSS 變數 | oklch 值 | 用途差異 |
|-------|---------|---------|---------|
| bg.base | `--background` | `oklch(0.145 0 0)` | 深灰黑背景 |
| fg.base | `--foreground` | `oklch(0.985 0 0)` | 近白文字 |
| surface.card | `--card` | `oklch(0.205 0 0)` | Card 比頁面亮一階 |
| brand.primary | `--primary` | `oklch(0.922 0 0)` | Dark 模式主按鈕變亮 |
| state.secondary | `--secondary` | `oklch(0.269 0 0)` | 次要元素背景 |
| state.destructive | `--destructive` | `oklch(0.704 0.191 22.216)` | Dark 模式紅色提亮 |
| border.base | `--border` | `oklch(1 0 0 / 10%)` | 半透明白邊框 |
| input.base | `--input` | `oklch(1 0 0 / 15%)` | 半透明 Input |
| chart.1 | `--chart-1` | `oklch(0.488 0.243 264.376)` | 紫藍 |
| chart.2 | `--chart-2` | `oklch(0.696 0.17 162.48)` | 綠松 |
| chart.3 | `--chart-3` | `oklch(0.769 0.188 70.08)` | 金 |
| chart.4 | `--chart-4` | `oklch(0.627 0.265 303.9)` | 紫 |
| chart.5 | `--chart-5` | `oklch(0.645 0.246 16.439)` | 橘紅 |
### 1.3 狀態色(非 shadcn token散落在業務元件
**裝置狀態徽章(`device-status.tsx`**使用 Tailwind 原生色:
| 狀態 | Tailwind class | 備註 |
|------|---------------|------|
| detected | `bg-gray-400` | 已偵測但未連線 |
| connecting | `bg-yellow-400` | 連線中 |
| connected | `bg-green-500` | 已連線 |
| flashing | `bg-yellow-500` | 燒錄中 |
| inferencing | `bg-blue-500` | 推論中 |
| error | `bg-red-500` | 錯誤 |
| disconnected | `bg-gray-400` | 已中斷 |
**注意**:這些顏色**未納入 Design Tokens**Design Review 指出這是一個 Minor 問題(詳見 `design-review.md`)。雛形階段保留現況。
### 1.4 字型
```css
--font-sans: var(--font-geist-sans);
--font-mono: var(--font-geist-mono);
```
使用 Vercel Geist 字體(`next/font`)。無其他字重 / 字級的 Token 定義,全由 Tailwind utility class 控制。
### 1.5 圓角
| Token | CSS 變數 | 計算值 |
|-------|---------|-------|
| radius.base | `--radius` | `0.625rem`10px |
| radius.sm | `--radius-sm` | `calc(var(--radius) - 4px)` = 6px |
| radius.md | `--radius-md` | `calc(var(--radius) - 2px)` = 8px |
| radius.lg | `--radius-lg` | `var(--radius)` = 10px |
| radius.xl | `--radius-xl` | `calc(var(--radius) + 4px)` = 14px |
| radius.2xl | `--radius-2xl` | `calc(var(--radius) + 8px)` = 18px |
| radius.3xl | `--radius-3xl` | `calc(var(--radius) + 12px)` = 22px |
| radius.4xl | `--radius-4xl` | `calc(var(--radius) + 16px)` = 26px |
Card 預設使用 `rounded-xl`14pxButton 預設 `rounded-md`8pxBadge 預設 `rounded-full`
### 1.6 間距(沿用 Tailwind 4 預設)
無自訂 spacing token全用 Tailwind `space-*` / `p-*` / `m-*` / `gap-*`4px 為 base`1`=4px、`2`=8px、`4`=16px、`6`=24px、`8`=32px
**常用間距決策(觀察自 local-tool**
- 頁面上下 spacing`space-y-6`24px
- Card 內垂直間距:`gap-6``space-y-3`
- Header 高度:`h-14`56px
- Sidebar 寬度:`w-60`240px
- 頁面主內容 padding`p-6``px-6`
- Icon 大小:`h-4 w-4`16px為主`h-5 w-5`20px為強調
### 1.7 Shadow
無自訂 shadow token使用 Tailwind 預設:
- Card`shadow-sm`
- Floating panel / Toast`shadow-lg`
- Buttonshadcn`shadow-xs`(低強度)
### 1.8 Z-index觀察自 local-tool未明確 token 化)
| 層級 | z-index | 用途 |
|------|--------|------|
| base | auto | 一般內容 |
| sticky | 30 | Header、Sidebar 的 sticky 狀態(如果有)|
| dropdown | 40 | Select、Popover |
| modal | 50 | Dialog、AlertDialog |
| toast | 50+ | Sonner toastSonner 內建) |
| floating tools | 50 | `/models` 的比較模式浮動工具列(`fixed bottom-6 z-50`|
### 1.9 Transition
無自訂 transition token使用 shadcn 內建:
- 按鈕:`transition-all`
- Input`transition-[color,box-shadow]`
- Sidebar 項目切換:`transition-colors`
- 持續時間:預設 Tailwind150ms無明確定義
---
## 2. Semantic Tokens語義映射
本層由 CSS 變數名稱本身承擔語義角色,不再做額外映射。以下是「用途 → 使用哪個 token」的對照
| 用途 | Token | class 範例 |
|------|-------|-----------|
| 頁面背景 | `--background` | `bg-background` |
| 主要文字 | `--foreground` | `text-foreground` |
| 卡片 / 區塊背景 | `--card` | `bg-card` |
| 輔助說明文字 | `--muted-foreground` | `text-muted-foreground` |
| 主要 CTA 按鈕 | `--primary` | `bg-primary text-primary-foreground` |
| 次要按鈕 | `--secondary` | `bg-secondary` |
| Outline 按鈕邊框 | `--border` | `border` |
| Hover 背景 | `--accent` | `hover:bg-accent` |
| 警告 / 危險操作 | `--destructive` | `bg-destructive` |
| Focus ring | `--ring` | `focus-visible:ring-ring` |
| 表單 Input 邊框 | `--input` | `border-input` |
| Sidebar 背景 | `--sidebar` | `bg-sidebar` |
| 圖表配色 | `--chart-1..5` | `fill-[var(--chart-1)]` |
### 2.1 新增的「半語義」類(雲端版 UI 使用)
以下**不新增 Token**,但約定用法,確保雲端版 UI 一致:
| 用途 | 實作方式 |
|------|---------|
| 裝置狀態:在線 | `bg-green-500`(保留既有設計) |
| 裝置狀態:掉線(離線) | `bg-gray-400` + `dark:bg-gray-600` |
| 裝置狀態:連線中 / 重連中 | `bg-yellow-400` + animate-pulse |
| 警告橫幅背景(如 udev hint | `bg-amber-50 dark:bg-amber-950/30` + `border-amber-300` |
| 成功提示綠 | 沿用 `bg-green-500` 或 Sonner success toast |
| 資訊提示藍 | `bg-blue-50 dark:bg-blue-950/30` + `border-blue-300` |
---
## 3. Component Tokens
Component 層在 shadcn/ui 系統下由 `cva` 變體處理,不維護獨立 token table。以下列出**元件在 Design Token 上的對應**
### 3.1 Button
| 變體 | 背景 | 文字 | Hover | Focus ring |
|------|------|------|-------|-----------|
| default | `--primary` | `--primary-foreground` | `bg-primary/90` | `--ring` |
| destructive | `--destructive` | `text-white` | `bg-destructive/90` | `--destructive/20` |
| outline | `--background` | `--foreground` | `bg-accent` + `text-accent-foreground` | `--ring` |
| secondary | `--secondary` | `--secondary-foreground` | `bg-secondary/80` | `--ring` |
| ghost | transparent | `--foreground` | `bg-accent` | `--ring` |
| link | transparent | `--primary` | `underline` | `--ring` |
| Size | 高度 | 水平 padding | 說明 |
|------|------|-------------|------|
| xs | 24px | 8px | 表格 / 密集列表 |
| sm | 32px | 12px | 卡片內按鈕 |
| default | 36px | 16px | 一般頁面按鈕 |
| lg | 40px | 24px | CTA 或表單提交 |
| icon | 36×36 | - | 純圖示按鈕(正方形) |
| icon-xs / sm / lg | 24/32/40 | - | 搭配 xs/sm/lg |
### 3.2 Card
- 背景:`--card`
- 文字:`--card-foreground`
- 邊框:`--border``border`
- 圓角:`rounded-xl`14px
- 內距:`py-6 px-6`
- Shadow`shadow-sm`
### 3.3 Badge
- Variants: `default` / `secondary` / `destructive` / `outline` / `ghost` / `link`
- 形狀:`rounded-full``px-2 py-0.5``text-xs font-medium`
- 色彩映射同 Button簡化版
### 3.4 Input
- 高度36px`h-9`
- 邊框:`--input`
- Focus ring`--ring/50` with `ring-[3px]`
- 無效狀態:`aria-invalid``border-destructive` + `ring-destructive/20`
- Dark Mode`bg-input/30`
### 3.5 DialogModal
- 背景:`--background`
- 邊框:`--border`
- 圓角:`rounded-lg`
- 最大寬度:依 context一般 `max-w-lg`512px
- Overlay黑色半透明shadcn 預設)
### 3.6 Sidebarlayout
- 寬度240px`w-60`
- 背景:`--sidebar`
- 邊框右:`--sidebar-border`
- 項目 active`bg-primary text-primary-foreground`
- 項目 hover非 active`bg-accent text-accent-foreground`
- Logo 區高度56px`h-14`
- 項目垂直 padding`py-2`8px高度 36px
### 3.7 新增元件的 Token 對應(雲端版)
| 元件 | 背景 | 文字 | 邊框 | 備註 |
|------|------|------|------|------|
| UserMenu Trigger | `--card` | `--foreground` | `--border` | Sidebar 底部新增 |
| PairingTokenCard | `--card` | `--foreground` | `--border` | Pairing 頁主要卡片 |
| PairingTokenDisplay | `--muted` | `font-mono` | `--border` | `vAc_` + 32 hex36 字元視覺切兩行複製為完整字串TTL 15 分鐘含倒數計時器 |
| RemoteDeviceBadge (online) | `bg-green-500` | `white` | - | 綠點 + 文字 |
| RemoteDeviceBadge (offline) | `bg-gray-400` | `white` | - | 灰點 + 文字 + 上次心跳時間 |
| RemoteDeviceBadge (degraded) | `bg-yellow-400` | - | - | 黃點 + animate-pulse |
| NetworkErrorBanner | `bg-amber-50` + `border-amber-300` | `text-amber-800` | - | Dark: `bg-amber-950/30` |
---
## 4. 不納入 Token 的設計決策(但需記錄)
| 決策 | 說明 |
|------|------|
| 使用 `oklch()` 而非 `hsl()` / `hex()` | Tailwind 4 + shadcn 新版慣例,色域廣、可感知線性變化 |
| 不定義 Typography scale | 全用 Tailwind 預設text-xs / sm / base / lg / xl / 2xl...),避免過度設計 |
| 不定義 Opacity scale | 用 Tailwind 預設(`/10` / `/20` / `/50` / `/90` |
| 不用 CSS Preprocessor | 純 Tailwind 4 + CSS variables簡化 build pipeline |
---
## 5. 給 Frontend Agent 的提醒
1. **直接複製** `local-tool/frontend/src/app/globals.css``visionA-frontend/src/app/globals.css`**完全不動**。
2. Dark Mode 跟隨系統(沿用 `ThemeSync`)。
3. 新元件一律用 CSS 變數 + Tailwind class不要寫 inline style、不要寫 color 的 hex / rgb。
4. 有新 token 需求(例如極少數的狀態色)先跟 Design Agent 討論,再決定是否加入 Token 或沿用現有。
5. 圖表色用 `--chart-1..5`,確保 Light / Dark Mode 自動切換。