# 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 於 `` 切換,由 `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`(14px),Button 預設 `rounded-md`(8px),Badge 預設 `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` - Button(shadcn):`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 toast(Sonner 內建) | | 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` - 持續時間:預設 Tailwind(150ms),無明確定義 --- ## 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 Dialog(Modal) - 背景:`--background` - 邊框:`--border` - 圓角:`rounded-lg` - 最大寬度:依 context,一般 `max-w-lg`(512px) - Overlay:黑色半透明(shadcn 預設) ### 3.6 Sidebar(layout) - 寬度: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 hex(36 字元),視覺切兩行,複製為完整字串;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 自動切換。