chore: STYLE_GUIDE.md
This commit is contained in:
+528
@@ -0,0 +1,528 @@
|
||||
# 前端样式设计规范 (STYLE_GUIDE)
|
||||
|
||||
> **版本**:v2.0 — 规范化版本
|
||||
>
|
||||
> **文档性质变更说明**:v1.0 由现有代码反向提炼而来,仅描述"现状",并列出大量"新旧并存 / 待统一"的问题清单。
|
||||
> **v2.0 起,本文档是唯一权威规范**:所有历史上并存的多套数值(多个品牌蓝、多个灰色、多套圆角体系等)已在本版本中**收敛为唯一官方取值**。
|
||||
>
|
||||
> - 🟢 **新代码 / 其他系统 / 新项目**:必须(MUST)按本文档执行,禁止再引入本文档之外的颜色、字号、圆角、间距任意值。
|
||||
> - 🟡 **存量 legacy 代码**:允许暂时保留(不要求立即批量重构),但**触碰到的每一处**(改动、重构、修 bug)都必须顺手改为符合本规范的取值,禁止在旧代码基础上"抄一份"旧的任意值到新地方。
|
||||
> - 本指南**不强制使用特定 UI 组件框架**(React/Vue/Tailwind/Ant Design 等均可),只强制**最终视觉呈现**(色值、字号、圆角、阴影、间距、过渡时长/缓动)与本文档一致。不同技术栈的团队,请把本文档中的 CSS 变量按第 12 节的方法映射到自己的 token/主题系统。
|
||||
|
||||
---
|
||||
|
||||
## 0. 规范优先级说明
|
||||
|
||||
文档中出现的关键词含义(参考 RFC 2119 风格):
|
||||
|
||||
| 关键词 | 含义 |
|
||||
|---|---|
|
||||
| **必须 / 禁止** | 强制性规则,新代码不得违反,Code Review 应作为拒绝合并的理由 |
|
||||
| **应当** | 强烈建议,没有特殊原因必须遵守;有正当理由例外时需在 PR 中说明 |
|
||||
| **可以** | 允许的做法,非强制 |
|
||||
|
||||
---
|
||||
|
||||
## 1. 设计概览
|
||||
|
||||
项目整体风格是 **浅色 + 深蓝侧栏** 的 SaaS 控制台风格,所有新页面 / 新模块必须延续此基调:
|
||||
|
||||
- **基调色**:极浅蓝灰背景 `#f3f6f9`,纯白卡片 `#ffffff`,深蓝侧栏 `#09233f`。
|
||||
- **品牌主色**:饱和中蓝 `#1978d4`(唯一官方品牌蓝,见 §2.7 废弃旧值列表)。
|
||||
- **状态色**:成功绿 `#18b979` / 危险红 `#d75b5b`(唯一官方危险色)/ 警告橙 `#e6a33c`。
|
||||
- **形状语言**:统一采用 `rounded-2xl / 3xl / 4xl` 圆角阶梯(4 / 6 / 8px 递增,见 §4.3),**禁止**新代码再使用任意像素圆角(如 `rounded-[7px]`)。
|
||||
- **字体**:Inter Variable(`/fonts/Inter-Variable.ttf`,weight 100–900)+ PingFang SC / Microsoft YaHei / system-ui 中文回落。
|
||||
- **阴影**:`shadow-md`(卡片)/ `shadow-xl`(对话框/抽屉),禁止新增自定义阴影任意值。
|
||||
- **动效**:统一 100–200ms 过渡(抽屉类组件可到 450ms),弹层统一用 `data-open`/`data-closed` 进出模式。
|
||||
|
||||
---
|
||||
|
||||
## 2. 色彩系统(唯一权威取值)
|
||||
|
||||
> **规则**:任何新代码中出现的颜色,必须来自本节表格中的具名 token 或对应 CSS 变量 / Tailwind 语义类。**禁止**在新代码里直接写裸 hex 值,除非本节明确未覆盖的一次性边缘场景(且需在 PR 中说明原因)。
|
||||
|
||||
### 2.1 Token 定义位置
|
||||
|
||||
- 品牌 token:`frontend/app/app.css` `@theme { ... }` 块。
|
||||
- 侧栏 token:`frontend/app/app.css` `@theme inline` + `:root { --sidebar-... }`。
|
||||
- shadcn 语义 token(`bg-primary` / `text-foreground` 等)实际值由 `@theme` 覆盖,UI 组件一律使用语义 token,不写 hex。
|
||||
|
||||
### 2.2 品牌色(Brand / Accent)
|
||||
|
||||
| 名称 | 十六进制 | CSS 变量 | 用途 |
|
||||
|---|---|---|---|
|
||||
| brand | `#1978d4` | `--color-brand` | 主色:CTA、链接、选中态、强调(对应 `bg-primary`/`text-primary`) |
|
||||
| brand-strong | `#0e5fb9` | `--color-brand-strong` | 主色按下/激活 |
|
||||
| brand-soft | `#edf6ff` | `--color-brand-soft` | 主色浅底:标签背景、提示行 |
|
||||
| **brand-deep**(新增) | `#0e5bad` | `--color-brand-deep` | 渐变按钮的深色结束端(替代历史上散落的 `#1268c9`/`#1175d8`/`#0e5bad` 等值) |
|
||||
|
||||
**渐变按钮官方写法**(如仍需渐变视觉的按钮):`linear-gradient(135deg, var(--color-brand), var(--color-brand-deep))`。**禁止**再手写新的渐变端点色值。
|
||||
|
||||
### 2.3 状态色
|
||||
|
||||
| 名称 | 十六进制 | CSS 变量 | 用途 |
|
||||
|---|---|---|---|
|
||||
| success / success-strong / success-soft | `#18b979` / `#0f7d55` / `#e8f7f1` | `--color-success*` | 成功提示、确认按钮 |
|
||||
| danger / danger-strong / danger-soft | `#d75b5b` / `#a94f4f` / `#fff6f6` | `--color-danger*` | 错误、删除、危险操作(对应 `bg-destructive`)|
|
||||
| warning / warning-soft | `#e6a33c` / `#fff0ee` | `--color-warning*` | 警示提示 |
|
||||
|
||||
### 2.4 中性文本 / 边框 / 背景
|
||||
|
||||
| 名称 | 十六进制 | CSS 变量 | 用途 |
|
||||
|---|---|---|---|
|
||||
| ink | `#27394d` | `--color-ink` | 主要正文 |
|
||||
| ink-muted | `#5d7186` | `--color-ink-muted` | 次要正文 |
|
||||
| ink-subtle | `#8b99a8` | `--color-ink-subtle` | 辅助说明、占位 |
|
||||
| **ink-caption**(新增) | `#748598` | `--color-ink-caption` | 表格表头/卡片小标签等"更淡一档"的说明文字(替代历史上 `#748598`/`#758497`/`#8796a6`/`#8a9aaa` 等近似灰色) |
|
||||
| line | `#dce4ec` | `--color-line` | 标准边框(对应 `border-border`),替代历史上 `#dce5ed`/`#dfe7ef`/`#dfe6ed`/`#e7ecf1`/`#e8edf2`/`#e0e7ee` 等近似边框色 |
|
||||
| line-soft | `#edf1f5` | `--color-line-soft` | 表格行/分隔线 |
|
||||
| bg | `#f3f6f9` | `--color-bg` | 页面背景 |
|
||||
| bg-panel | `#ffffff` | `--color-bg-panel` | 卡片/面板背景 |
|
||||
| bg-canvas | `#f9fbfd` | `--color-bg-canvas` | 画布背景 |
|
||||
| bg-log | `#17212b` | `--color-bg-log` | 日志/代码块深色背景 |
|
||||
|
||||
### 2.5 侧栏 token(独立主题)
|
||||
|
||||
| 名称 | 值 | 用途 |
|
||||
|---|---|---|
|
||||
| `--sidebar-background` | `#09233f` | 深蓝侧栏底 |
|
||||
| `--sidebar-foreground` | `#c9d7e7` | 侧栏默认文字 |
|
||||
| `--sidebar-primary` | `#1479e8` | 侧栏内强调主色 |
|
||||
| `--sidebar-primary-foreground` | `#ffffff` | 主色文字 |
|
||||
| `--sidebar-accent` | `rgba(255,255,255,0.06)` | 选中态背景 |
|
||||
| `--sidebar-accent-foreground` | `#ffffff` | 选中态文字 |
|
||||
| `--sidebar-border` | `rgba(255,255,255,0.08)` | 侧栏内分隔线 |
|
||||
| `--sidebar-ring` | `#5ca9ff` | focus ring |
|
||||
|
||||
**规则**:任何侧栏相关的自定义样式(如背景渐变)必须引用 `var(--sidebar-background)` 等变量,**禁止**再硬编码 `#09233f`。
|
||||
|
||||
### 2.6 shadcn 语义 token 映射
|
||||
|
||||
| Tailwind 类 | 对应变量 | 用途 |
|
||||
|---|---|---|
|
||||
| `bg-primary` / `text-primary` / `border-primary` | `--color-brand` | 主按钮、链接 |
|
||||
| `bg-secondary` | 浅灰 | 次级按钮 / 输入框默认态 |
|
||||
| `bg-destructive` / `text-destructive` | `--color-danger` | 危险按钮 |
|
||||
| `bg-muted` / `text-muted-foreground` | 浅灰底 + `--color-ink-muted` | 次要容器、辅助文字 |
|
||||
| `bg-popover` / `text-popover-foreground` | 白底 | 浮层、菜单、对话框 |
|
||||
| `bg-background` / `text-foreground` | 页面背景 + `--color-ink` | body、文本默认 |
|
||||
| `bg-card` / `text-card-foreground` | 卡片 | Card 容器 |
|
||||
| `bg-input` / `border-input` | 浅灰 | 输入框背景 |
|
||||
| `border-border` | `--color-line` | 通用边框 |
|
||||
| `border-ring` / `ring-ring` | 浅蓝 | focus 边框 / 焦点环 |
|
||||
| `border-destructive` | `--color-danger` | 错误状态边框 |
|
||||
|
||||
### 2.7 已废弃色值(禁止新代码使用)
|
||||
|
||||
以下 hex 曾在 legacy 页面中散落使用,**新代码严禁再出现**,一律替换为 §2.2–2.4 对应 token:
|
||||
|
||||
| 废弃值 | 替换为 |
|
||||
|---|---|
|
||||
| `#1881e7` / `#126ac3` / `#1268c9` / `#1175d8` / `#0e5bad` / `#1479e8`(页面内联渐变)/ `#2279c7` | `--color-brand` / `--color-brand-strong` / `--color-brand-deep`(渐变见 §2.2) |
|
||||
| `#e74c3c` | `--color-danger`(`#d75b5b`) |
|
||||
| `#748598` / `#758497` / `#8796a6` / `#8a9aaa` | `--color-ink-caption`(新代码首选)或 `--color-ink-muted` / `--color-ink-subtle`(视层级而定) |
|
||||
| `#dce5ed` / `#dfe7ef` / `#dfe6ed` / `#e7ecf1` / `#e8edf2` / `#e0e7ee` | `--color-line` |
|
||||
| `#81b2e7` | `--color-brand-soft` 场景下配合使用,或改用 `--color-brand` 的透明度变体(如 `text-primary/70`),不再单独定义新 hex |
|
||||
|
||||
---
|
||||
|
||||
## 3. 字体系统
|
||||
|
||||
### 3.1 字体族
|
||||
|
||||
```css
|
||||
--font-sans: Inter, "PingFang SC", "Microsoft YaHei", system-ui, sans-serif;
|
||||
```
|
||||
|
||||
字体文件:`public/fonts/Inter-Variable.ttf`(含 italic 变体),`font-display: swap`。
|
||||
|
||||
### 3.2 字号阶梯(唯一官方取值)
|
||||
|
||||
**规则**:新代码**必须**从下表取值,**禁止**再使用未定义的任意 `text-[Npx]`。
|
||||
|
||||
| Token / 类 | 像素 | 用途 |
|
||||
|---|---|---|
|
||||
| `text-4xs`(新增 token) | 8px | badge / 角标(原 `text-[8px]`) |
|
||||
| `text-3xs`(新增 token) | 9px | 极小辅助文字(原 `text-[9px]`) |
|
||||
| `text-2xs`(新增 token) | 10px | 小标签 / 数字 / 计数(原 `text-[10px]`,历史最高频) |
|
||||
| `text-xs` | 12px | 表头 / 小按钮 / 行内说明(统一原 `text-[11px]`/`text-[12px]`/`text-[13px]`) |
|
||||
| `text-sm` | 14px | 默认正文 / UI 组件默认字号 |
|
||||
| `text-base` | 16px | 强调正文 |
|
||||
| `text-xl` | 20px | 小标题 |
|
||||
| `text-2xl`+ | 24px+ | 大标题 / 特殊展示字号,按需在设计评审中确定 |
|
||||
|
||||
> 需要在 `app.css` 的 `@theme` 中补充定义:
|
||||
> ```css
|
||||
> --text-2xs: 0.625rem; /* 10px */
|
||||
> --text-3xs: 0.5625rem; /* 9px */
|
||||
> --text-4xs: 0.5rem; /* 8px */
|
||||
> ```
|
||||
> 在此之前,可临时使用 `text-[10px]` 等写法,但一旦 token 落地必须替换。
|
||||
|
||||
### 3.3 字重
|
||||
|
||||
| Token | 值 | 用途 |
|
||||
|---|---|---|
|
||||
| `font-medium` | 500 | UI 组件默认(按钮/CardTitle/DialogTitle) |
|
||||
| **`font-medium-plus`(新增 token)** | 650 | Topbar / 主按钮等需要"比 medium 重、比 semibold 轻"的强调场景(原任意值 `font-[650]`,现固化为官方 token,禁止再写 `font-[650]`) |
|
||||
| `font-semibold` | 600 | 强调文本 |
|
||||
| `font-bold` | 700 | 标题 |
|
||||
| `font-extrabold` | 800 | 大数字 / 品牌展示 |
|
||||
|
||||
> 需在 `@theme` 中补充:`--font-weight-medium-plus: 650;`,并在 Tailwind 中暴露为 `font-medium-plus` 工具类。
|
||||
|
||||
### 3.4 行高 / 字间距
|
||||
|
||||
- 默认行高 1.5;对话框标题用 `leading-none`;长文本正文(如 `.notebook-md p`)用 `line-height: 1.6`。
|
||||
- 字间距仅用于大写字母标签:`tracking-[0.08em]` ~ `tracking-[0.12em]`,**禁止**在正文中使用额外字间距。
|
||||
|
||||
---
|
||||
|
||||
## 4. 间距、圆角与布局
|
||||
|
||||
### 4.1 基础网格
|
||||
|
||||
Tailwind 默认 4px 网格(`0.25rem`),不自定义 `--spacing` 基数。
|
||||
|
||||
### 4.2 间距 Token(唯一官方取值)
|
||||
|
||||
**规则**:以下为新代码必须优先使用的语义间距 token,**禁止**再随手写 `px-[22px]` 这类任意值。
|
||||
|
||||
| Token(新增) | 值 | 用途(替代原任意值) |
|
||||
|---|---|---|
|
||||
| `--spacing-page-x` | 22px | 页面左右内边距(原 `px-[22px]` / `mx-[22px]`) |
|
||||
| `--spacing-button-x` | 15px | 主按钮水平内边距(原 `px-[15px]`) |
|
||||
| `--spacing-gap-icon` | 7px | 按钮内图标间距(原 `gap-[7px]`) |
|
||||
| `--spacing-gap-sm` | 5px | 小行距(原 `gap-[5px]`) |
|
||||
| `--spacing-gap-md` | 9px | 列表/区块间距(原 `gap-[9px]` / `gap-[10px]` 就近取整为该 token 或 `gap-2.5`) |
|
||||
|
||||
其余场景优先使用 Tailwind 内建 token:`p-2.5` / `p-3` / `p-4` / `p-6` / `gap-1.5` / `gap-2` / `gap-6` / `px-3` / `py-1`。
|
||||
|
||||
### 4.3 圆角规范(唯一官方阶梯)
|
||||
|
||||
**规则**:新代码**必须**使用以下阶梯,**禁止**再引入新的任意像素圆角。历史任意值按下表强制迁移:
|
||||
|
||||
| 官方 Token | 像素 | 用途 | 替代的历史任意值 |
|
||||
|---|---|---|---|
|
||||
| `rounded`(Tailwind 默认) | 4px | 极小元素(icon 容器等) | `rounded-[4px]` |
|
||||
| `rounded-md` | 6px | 小型控件、legacy 按钮/输入 | `rounded-[5px]` / `rounded-[6px]` / `rounded-[7px]` |
|
||||
| `rounded-lg` | 8px | 中等卡片/列表项 | `rounded-[9px]` / `rounded-[10px]` |
|
||||
| `rounded-xl` | 12px | 大号卡片、Tooltip | `rounded-[11px]` / `rounded-[13px]` |
|
||||
| `rounded-2xl` | 16px | Textarea / Skeleton | — |
|
||||
| `rounded-3xl` | 24px | Input / Combobox 弹出层 | — |
|
||||
| `rounded-4xl` | 32px | Button / Card / Dialog / Drawer / Sheet(最高一级视觉容器) | — |
|
||||
| `rounded-full` | — | 头像 / 徽章 | — |
|
||||
|
||||
> **组件分层原则**:交互控件从小到大遵循 `md → lg → xl → 2xl → 3xl → 4xl` 依次递增,容器级别越大(对话框、卡片)圆角越大,行内小控件(checkbox、badge)圆角越小。新组件设计时先确定"层级",再从表中取值,不要自创中间值。
|
||||
|
||||
### 4.4 阴影(唯一官方取值)
|
||||
|
||||
| Token | 用途 |
|
||||
|---|---|
|
||||
| `shadow-md` | Card 默认阴影 |
|
||||
| `shadow-lg` | Combobox / 下拉菜单 |
|
||||
| `shadow-xl` | Dialog / Sheet / Drawer / Sidebar 菜单 |
|
||||
|
||||
**规则**:**禁止**新代码使用自定义阴影任意值(如 `shadow-[0_6px_15px_rgb(...)]`)。如确需强调阴影(例如渐变主按钮的"投色阴影"),必须先在本文档中补充为具名 token 后才能使用。
|
||||
|
||||
### 4.5 边框
|
||||
|
||||
- 默认宽度 `1px`(Tailwind `border`)。
|
||||
- 输入类组件:默认 `border-transparent`,focus 时 `focus-visible:border-ring` + `focus-visible:ring-3 focus-visible:ring-ring/30`。
|
||||
- 危险态:`aria-invalid:border-destructive` + `aria-invalid:ring-3 aria-invalid:ring-destructive/20`。
|
||||
- 边框颜色统一使用 `border-border`(`--color-line`),**禁止**再写 `border-[#dfe6ee]` 等任意 hex(见 §2.7)。
|
||||
|
||||
### 4.6 布局
|
||||
|
||||
- 页面容器:`min-width: 1120px`,桌面优先布局(当前产品定位不适配移动端,如需移动端适配需局部覆盖,不改全局)。
|
||||
- 侧栏宽度:展开 `16rem` / 收起 `3rem` / 移动端 `18rem`。
|
||||
- 两栏布局参考:`grid-cols-[310px_minmax(0,1fr)] max-xl:grid-cols-[285px_minmax(0,1fr)]`。
|
||||
- Dashboard 网格参考:`min-[1201px]:grid-cols-[minmax(0,1.6fr)_minmax(310px,0.9fr)] max-[1200px]:grid-cols-1`。
|
||||
|
||||
### 4.7 断点
|
||||
|
||||
使用 Tailwind v4 默认断点:`sm 40rem` / `md 48rem` / `lg 64rem` / `xl 80rem` / `2xl 96rem`,不自定义。响应式优先用 `max-xl:` / `max-[1200px]:` / `sm:` 等既有写法保持一致性。
|
||||
|
||||
---
|
||||
|
||||
## 5. 组件视觉规范(强制规格,可用任意技术栈实现同等效果)
|
||||
|
||||
> 以下为各组件的**强制视觉规格**。使用 React + shadcn 的团队直接复用 `app/components/ui/*`;使用其他框架(Vue/Ant Design/Element Plus 等)的团队,必须在自己的组件层重新实现,但颜色、圆角、尺寸、状态视觉必须与下表完全一致。
|
||||
|
||||
### 5.1 Button
|
||||
|
||||
- 圆角 `rounded-4xl`;字号默认 `text-sm`;字重 `font-medium`;过渡 `transition-all`。
|
||||
- 尺寸:默认 `h-9 px-3` / `xs h-6 px-2.5` / `sm h-8 px-3` / `lg h-10 px-4` / `icon 36×36` / `icon-xs 24×24` / `icon-sm 32×32` / `icon-lg 40×40`。
|
||||
- 状态:default `bg-primary` + 白字;hover `bg-primary/80`;active `translate-y-px`;focus `border-ring` + `ring-3 ring-ring/30`;disabled `pointer-events-none opacity-50`;invalid `border-destructive ring-3 ring-destructive/20`。
|
||||
- 内部 svg 未指定尺寸时自动 `size-4`(16px)。
|
||||
|
||||
### 5.2 Input
|
||||
|
||||
- 圆角 `rounded-3xl`;高度 `h-9`(36px);字号 `text-sm`;背景 `bg-input/50`。
|
||||
- 状态:placeholder `text-muted-foreground`;focus `border-ring`(无 ring 阴影);disabled `cursor-not-allowed opacity-50`;invalid `border-destructive`。
|
||||
|
||||
### 5.3 Textarea
|
||||
|
||||
- 圆角 `rounded-2xl`;最小高 `min-h-16`(64px);不可手动 resize;内边距 `px-3 py-3`;focus 额外带 `ring-3 ring-ring/30`。
|
||||
|
||||
### 5.4 Checkbox
|
||||
|
||||
- 尺寸 `size-4`(16px);圆角 `rounded-md`(6px,统一自原 `rounded-[5px]`);背景 `bg-input/90`。
|
||||
- 状态:checked `border-primary bg-primary` + 白色 `CheckIcon`;focus `border-ring ring-3 ring-ring/30`;disabled `cursor-not-allowed opacity-50`;invalid `border-destructive ring-3 ring-destructive/20`。
|
||||
|
||||
### 5.5 Combobox / Select
|
||||
|
||||
- Trigger 与 Input 一致,右侧 `ChevronDownIcon size-4 text-muted-foreground`。
|
||||
- Content:圆角 `rounded-3xl`,背景 `bg-popover`,阴影 `shadow-lg`,`ring-1 ring-foreground/5`。
|
||||
- Item 右侧固定 `size-4` 的 `CheckIcon` 占位槽;Separator `-mx-1.5 my-1.5 h-px bg-border`。
|
||||
- 入场:按 side 滑入 + `fade-in-0 zoom-in-95`,约 100ms。
|
||||
|
||||
### 5.6 Card
|
||||
|
||||
- 圆角 `rounded-4xl`;背景 `bg-card`;阴影 `shadow-md`;`ring-1 ring-foreground/5`;内边距通过 `--card-spacing`(default 24px / sm 16px)。
|
||||
- 子区块:`CardTitle`(`text-base font-medium`)/ `CardDescription`(`text-sm text-muted-foreground`)/ `CardContent` / `CardFooter`。
|
||||
|
||||
### 5.7 Table
|
||||
|
||||
- 外包 `div.overflow-x-auto`,表格本体 `w-full text-sm`。
|
||||
- `TableRow`:`border-b`,`hover:bg-muted/50`,选中 `data-[state=selected]:bg-muted`。
|
||||
- `TableHead`:高 `h-12`(48px),内边距 `px-3`,`font-medium`,`whitespace-nowrap`。
|
||||
- `TableCell`:内边距 `p-3`,不换行;`TableCaption`:`mt-4 text-sm text-muted-foreground`。
|
||||
|
||||
### 5.8 Dialog / Sheet / Drawer
|
||||
|
||||
| 类型 | 圆角 | 阴影 | 背景 | 进场动画 |
|
||||
|---|---|---|---|---|
|
||||
| Dialog | `rounded-4xl` | `shadow-xl` + `ring-1 ring-foreground/5` | `bg-popover` | `fade-in-0 zoom-in-95` ~100ms |
|
||||
| Sheet | `rounded-4xl` | `shadow-xl` | `bg-popover` | 按 side 平移 `2.5rem` ~200ms |
|
||||
| Drawer | `rounded-4xl border border-popover` | `shadow-xl` | `bg-popover` | `duration-450` + `cubic-bezier(0.22,1,0.36,1)`,支持 swipe |
|
||||
|
||||
- 遮罩层统一 `bg-black/30` + `supports-backdrop-filter:backdrop-blur-sm`。
|
||||
- 关闭按钮:右上 `top-4 right-4`,icon-sm ghost(32×32,浅灰背景),内含 `XIcon`。
|
||||
- **三种动画时长差异属官方设计,禁止拉平统一**:对话框类交互 ≤ 200ms,抽屉/底栏类模拟物理滑动 ≤ 450ms。
|
||||
|
||||
### 5.9 AlertDialog
|
||||
|
||||
与 Dialog 同布局,唯一差异:标题字号 `text-lg`(Dialog 为 `text-base`),用于强调警示内容。
|
||||
|
||||
### 5.10 Tooltip
|
||||
|
||||
- 圆角 `rounded-xl`;背景 `bg-foreground`(反色);文字 `text-background`;字号 `text-xs`;内边距 `px-3 py-1.5`。
|
||||
- 箭头:`size-2.5 rotate-45 rounded-[2px]`,与背景同色。
|
||||
- 进场:`fade-in-0 zoom-in-95`,约 100ms,按 side 滑入。
|
||||
|
||||
### 5.11 Toast(Sonner)
|
||||
|
||||
通过 CSS 变量桥接品牌色,**禁止**脱离变量单独定义 toast 颜色:
|
||||
|
||||
```css
|
||||
--normal-bg: var(--popover);
|
||||
--normal-text: var(--popover-foreground);
|
||||
--normal-border: var(--border);
|
||||
--border-radius: var(--radius);
|
||||
```
|
||||
|
||||
图标统一 `size-4`:`CircleCheckIcon` / `InfoIcon` / `TriangleAlertIcon` / `OctagonXIcon` / `Loader2Icon animate-spin`。
|
||||
|
||||
### 5.12 Sidebar
|
||||
|
||||
- 宽度:展开 `16rem` / 收起 `3rem` / 移动端 `18rem`。
|
||||
- 深色专属主题:背景 `var(--sidebar-background)`、文字 `var(--sidebar-foreground)`、强调色 `var(--sidebar-primary)`、选中态背景 `var(--sidebar-accent)`(**必须**引用变量,禁止硬编码 hex,见 §2.5)。
|
||||
- 顶部装饰渐变:`radial-gradient(circle at 10% 1%, rgb(28 105 186 / 25%), transparent 27%), var(--sidebar-background)`。
|
||||
- 收起按钮图标:`PanelLeftIcon`(16px)。
|
||||
|
||||
### 5.13 Skeleton / Separator
|
||||
|
||||
- Skeleton:`animate-pulse rounded-2xl bg-muted`。
|
||||
- Separator:`shrink-0 bg-border`,水平 `h-px w-full`,垂直 `w-px self-stretch`。
|
||||
|
||||
### 5.14 InputGroup
|
||||
|
||||
`InputGroup` / `InputGroupAddon`(`inline-start` / `inline-end` / `block-start` / `block-end`)/ `InputGroupButton` / `InputGroupText` / `InputGroupInput` / `InputGroupTextarea`;addon 点击时焦点转交给兄弟 `<input>`。addon 文本 `text-muted-foreground text-sm font-medium`;kbd 元素 `rounded-3xl bg-muted-foreground/10 px-1.5`。
|
||||
|
||||
### 5.15 Legacy 共享视觉类(仅用于维护存量页面,新代码禁止新增引用)
|
||||
|
||||
以下类色值已在本文档中被官方 token 覆盖,**新页面不得再引用这些类**;修改已使用这些类的旧页面时,应顺势替换为 §5.1–§5.14 的现代规格:
|
||||
|
||||
| 类 | 视觉规格(供比对迁移) |
|
||||
|---|---|
|
||||
| `.icon-button` | 34×34,边框改为 `border-border`,圆角改为 `rounded-md`,hover 背景改为 `bg-muted` |
|
||||
| `.avatar` | 34×34 圆形,渐变改为 `linear-gradient(135deg, var(--color-brand), var(--color-brand-strong))` |
|
||||
| `.primary-button` | 迁移为 `Button`(`variant="default"`),渐变改为 `var(--color-brand)` → `var(--color-brand-deep)` |
|
||||
| `.secondary-button` | 迁移为 `Button`(`variant="outline"`) |
|
||||
| `.button-spinner` | 迁移为 `Loader2Icon animate-spin`(Toast/Button loading 态统一图标方案,见 §6.1) |
|
||||
|
||||
---
|
||||
|
||||
## 6. 图标与动效
|
||||
|
||||
### 6.1 图标
|
||||
|
||||
- 图标库:**`lucide-react`**(线条 1.5px 描边风格),新代码必须使用该图标库;若因技术栈限制需换库,**必须**保证线条粗细、视觉重量与 lucide 一致。
|
||||
- 尺寸规范:`size-4`(16px,按钮/菜单项默认)/ `size-3.5`(14px,Checkbox)/ `size-2.5`(10px,Tooltip 箭头)。
|
||||
- Button 内 svg 未指定尺寸时自动 `size-4`,新实现须遵循此约定。
|
||||
- 官方高频图标:`XIcon` / `CheckIcon` / `ChevronDownIcon` / `PanelLeftIcon` / `CircleCheckIcon` / `InfoIcon` / `TriangleAlertIcon` / `OctagonXIcon` / `Loader2Icon`。**所有 loading 态一律使用 `Loader2Icon animate-spin`**,禁止再实现新的 spinner 动画(替代原 `.button-spinner` + `spin` keyframes)。
|
||||
|
||||
### 6.2 过渡时长(唯一官方取值)
|
||||
|
||||
| Token | 用途 |
|
||||
|---|---|
|
||||
| `duration-100` | Dialog / AlertDialog / Sonner 进出 |
|
||||
| `duration-150` | Sheet 遮罩 |
|
||||
| `duration-200` | Sidebar / Sheet 主体 |
|
||||
| `duration-450` | Drawer(模拟 iOS 滑动手感,唯一允许超过 200ms 的场景) |
|
||||
| `duration-0` | 手势拖拽(swipe)中临时禁用过渡 |
|
||||
|
||||
**规则**:新增弹层组件必须归类到以上五档之一,不得自创新的时长值。
|
||||
|
||||
### 6.3 缓动函数
|
||||
|
||||
| Token | 用途 |
|
||||
|---|---|
|
||||
| `ease-linear` | 旋转 / 进度条 |
|
||||
| `ease-in-out` | 通用过渡 |
|
||||
| `ease-out` | 模态入场 |
|
||||
| `ease-[cubic-bezier(0.32,0.72,0,1)]` | Drawer 遮罩 |
|
||||
| `ease-[cubic-bezier(0.22,1,0.36,1)]` | Drawer 主体("expo out"手感) |
|
||||
|
||||
### 6.4 自定义关键帧
|
||||
|
||||
| keyframes | 时长 / 缓动 | 用途 |
|
||||
|---|---|---|
|
||||
| `shimmer` | 1.3s linear infinite | 骨架屏背景流光(`.tree-skeleton-bar`) |
|
||||
| `lock-pulse` | 1.8s ease-in-out infinite | 编辑中状态点呼吸(50% 处 opacity 0.5 + scale 0.78) |
|
||||
| `modal-in` | 0.18s ease-out | 弹窗从 `translateY(8px) scale(0.985)` 进入 |
|
||||
| `spin` | 0.7s linear infinite | **已废弃**,新代码统一用 `animate-spin`(Tailwind 内建) |
|
||||
|
||||
> `toast-in` 已废弃(Sonner 接管),新代码不得再引用。
|
||||
|
||||
### 6.5 通用动画工具
|
||||
|
||||
- `animate-in` / `animate-out`(shadcn tw-animate-css 工具类)。
|
||||
- `data-open:animate-in data-open:fade-in-0 data-open:zoom-in-95` / `data-closed:animate-out data-closed:fade-out-0 data-closed:zoom-out-95` —— 弹层组件**必须**遵循此统一动效模式。
|
||||
- `data-[side=...]:slide-in-from-{top|bottom|left|right|inline-start|inline-end}-2` —— 弹出层按侧滑入的唯一官方写法。
|
||||
- `animate-pulse`(Skeleton)/ `animate-spin`(Loader)。
|
||||
|
||||
---
|
||||
|
||||
## 7. 命名与代码风格
|
||||
|
||||
### 7.1 文件 / 目录
|
||||
|
||||
- 路由文件集中在 `app/routes/`,业务页面按域拆到 `app/features/{module}/`。
|
||||
- 共享原语在 `app/components/ui/<name>.tsx`,域内共享在 `app/components/common/<Name>.tsx`。
|
||||
- 工具函数:`app/lib/utils.ts`(`cn()` = `twMerge(clsx(...))`)。
|
||||
- 样式入口:**只允许一个 CSS 文件** `app/app.css`,由 `app/root.tsx` 唯一一次 `import "./app.css"` 引入;**禁止**新增分散的样式文件。
|
||||
|
||||
### 7.2 组件命名
|
||||
|
||||
- UI 组件函数名使用 **PascalCase**:`Button` / `CardHeader` / `DialogTitle` / `SidebarMenuButton`。
|
||||
- 每个 UI 元素**必须**带 `data-slot="..."` 属性(如 `button` / `card-header` / `dialog-content`),便于父级选择器和自动化测试定位。
|
||||
|
||||
### 7.3 类名拼接
|
||||
|
||||
- 统一用 `cn(...)`(`~/lib/utils`,即 `twMerge(clsx(...))`)拼装类名,**禁止**手写字符串模板拼接类名。
|
||||
- 组件变体用 `cva(...)` 描述(参考 `Button` / `InputGroupAddon`)。
|
||||
- 非 Tailwind 技术栈:最终输出的类名/样式必须与 §2–§6 的视觉规格一致。
|
||||
|
||||
### 7.4 CSS 类命名约定
|
||||
|
||||
- shadcn 风格类**无 BEM**,纯功能化(`card-title` / `dialog-content`),依赖 `data-slot` + Tailwind 工具类定位。
|
||||
- `@layer utilities` 中的历史类沿用 kebab-case(如 `scrollbar-thin` / `dashboard-hero-shell` 等),**新增**该层的类也必须用 kebab-case。
|
||||
- **颜色 / 间距 token 优先**:新组件必须优先使用 §2/§4 的语义 token(`bg-primary` / `text-foreground` / `border-border`),**禁止**写裸 hex 或任意值;确无对应 token 时,先补充 token 定义,再使用。
|
||||
|
||||
### 7.5 路径别名
|
||||
|
||||
```ts
|
||||
"~": "frontend/app"
|
||||
"components": "~/components"
|
||||
"utils": "~/lib/utils"
|
||||
"ui": "~/components/ui"
|
||||
"lib": "~/lib"
|
||||
"hooks": "~/hooks"
|
||||
```
|
||||
|
||||
### 7.6 项目依赖版本(参考,非强制技术选型)
|
||||
|
||||
| 角色 | 库 | 版本 |
|
||||
|---|---|---|
|
||||
| 原语 | `@base-ui/react` | ^1.7.0 |
|
||||
| 变体 | `class-variance-authority` | ^0.7.1 |
|
||||
| 类合并 | `clsx` + `tailwind-merge` | ^2.1.1 / ^3.6.0 |
|
||||
| 图标 | `lucide-react` | ^1.33.0 |
|
||||
| 样式 | `tailwindcss` + `@tailwindcss/vite` | ^4.2.2 |
|
||||
| 动画 | `tw-animate-css` | ^1.4.0 |
|
||||
| Toast | `sonner` | ^2.0.8 |
|
||||
| 路由 | `react-router` / `@react-router/dev` | ^8 |
|
||||
| 状态 | `zustand` | ^5.0.14 |
|
||||
| 表格 | `@tanstack/react-table` | ^9.1.2 |
|
||||
|
||||
> 新模块/新项目如使用其他技术栈(Vue + Naive UI / Element Plus / Ant Design 等),必须按 §2/§3/§4/§6 的视觉规格在自己的主题系统中重新定义等价 token,保持视觉一致。
|
||||
|
||||
---
|
||||
|
||||
## 8. app.css 需新增的官方 Token(落地清单)
|
||||
|
||||
> 本文档 v2.0 相比 v1.0 新增/固化了以下 token,**必须**在 `app.css` 的 `@theme` 中补充定义,作为本规范落地的第一步:
|
||||
|
||||
```css
|
||||
@theme {
|
||||
/* 字号 */
|
||||
--text-2xs: 0.625rem; /* 10px */
|
||||
--text-3xs: 0.5625rem; /* 9px */
|
||||
--text-4xs: 0.5rem; /* 8px */
|
||||
|
||||
/* 字重 */
|
||||
--font-weight-medium-plus: 650;
|
||||
|
||||
/* 品牌色补充 */
|
||||
--color-brand-deep: #0e5bad;
|
||||
|
||||
/* 中性色补充 */
|
||||
--color-ink-caption: #748598;
|
||||
|
||||
/* 间距补充 */
|
||||
--spacing-page-x: 22px;
|
||||
--spacing-button-x: 15px;
|
||||
--spacing-gap-icon: 7px;
|
||||
--spacing-gap-sm: 5px;
|
||||
--spacing-gap-md: 9px;
|
||||
}
|
||||
```
|
||||
|
||||
落地后需同步在 Tailwind 中暴露对应工具类(如 `font-medium-plus`),并对 §2.7、§4.3、§5.15 中列出的旧任意值做替换。
|
||||
|
||||
---
|
||||
|
||||
## 9. 跨技术栈适配指引
|
||||
|
||||
若其他系统/新项目**不使用** React + Tailwind + shadcn 技术栈,请按以下方式对齐:
|
||||
|
||||
1. **色彩**:将 §2 全部 CSS 变量原样复制为自己主题系统的变量(如 Ant Design 的 `token`、Element Plus 的 CSS 变量、Vue 的 SCSS 变量),变量名可保留 `--color-*` 前缀便于跨项目检索。
|
||||
2. **字体**:引入同一份 `Inter-Variable.ttf` 字体文件,字号阶梯必须与 §3.2 表格一一对应(值相同,token 名可按自身框架习惯命名,但需在文档中注明与本表的映射关系)。
|
||||
3. **圆角/间距/阴影**:直接照抄 §4 的像素值,不需要用相同的 Tailwind 类名,但**数值必须相等**。
|
||||
4. **组件视觉**:对照 §5 逐项还原状态(default/hover/active/focus/disabled/invalid)与尺寸,不要求相同 DOM 结构。
|
||||
5. **动效**:过渡时长与缓动函数直接照抄 §6.2/§6.3 数值。
|
||||
6. 完成对齐后,在自己项目的 README 或设计文档中注明"视觉规范参照 STYLE_GUIDE.md vX.X",便于后续版本追踪。
|
||||
|
||||
---
|
||||
|
||||
## 附:shadcn 配置(参考)
|
||||
|
||||
```json
|
||||
{
|
||||
"style": "base-luma",
|
||||
"tsx": true,
|
||||
"tailwind": { "config": "", "css": "app/app.css", "baseColor": "neutral", "cssVariables": true },
|
||||
"iconLibrary": "lucide",
|
||||
"aliases": {
|
||||
"components": "~/components",
|
||||
"utils": "~/lib/utils",
|
||||
"ui": "~/components/ui",
|
||||
"lib": "~/lib",
|
||||
"hooks": "~/hooks"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**版本摘要**:React/React DOM 19.2.7 · React Router 8 · Tailwind CSS 4.2.2 · `@tailwindcss/vite` 4.2.2 · `@base-ui/react` 1.7.0 · `class-variance-authority` 0.7.1 · `lucide-react` 1.33.0 · `shadcn` CLI 4.19.0 · `sonner` 2.0.8 · `tw-animate-css` 1.4.0 · `tailwind-merge` 3.6.0 · `zustand` 5.0.14。
|
||||
Reference in New Issue
Block a user