跳转到内容

设计规范 · 共享核心

本页是全项目 UI 的唯一事实源。macOS 与 Windows 的平台差异见 macOS 平台层 与 Windows 平台层;逐控件正反例见 组件附录。

参考源(评审时可逐条核对):Apple《Human Interface Guidelines》macOS 部分、 Microsoft《Windows app design(Fluent / WinUI 3)》、JetBrains《UI Guidelines》;备查 GNOME / KDE HIG。

  • 适用于 src/(框架壳、设置页、示例插件)与 plugins/(所有工具插件)的全部前端 UI。
  • 执行手段(缺一不可):
    1. 本页 + 平台文档 + 附录:设计与评审依据;
    2. Token 层(src/assets/index.css):所有视觉取值只能取自 token,禁止任意值;
    3. pnpm lint:scripts/lint-design.mjs 机器拦截旧配方(见 §6 反例清单);
    4. PR 评审清单(§7):每次改动逐条自检。
  • 本文中的「必须 / 禁止」是硬约束;「建议」可按场景取舍,但需在 PR 里写明理由。

取自 HIG《Design principles》、Fluent《Design principles》与 JetBrains 的交集,并给出本项目的落地判据。

原则落地判据
清楚优先一屏一个主任务;信息靠层级(顺序、间距、对比)表达,不靠装饰;设置项能少不多,只在与任务相关的页面就近提供
即时反馈交互在 pointer-down 就有反馈;<1s 的操作不显示 spinner;长任务可取消并显示进度;错误就地说明(不弹窗、不道歉)
可撤销优先于确认能撤销就不拦截;只有不可撤销且后果严重的操作才用 Alert 确认
键盘可达所有功能都能用键盘完成;焦点可见且顺序合理;快捷键在界面中可见;Esc 关闭浮层、Enter 触发默认动作
克制装饰颜色只用于语义与交互;材质只用于分层;动效只用于解释因果;盒子不叠盒子(用内边距与对齐表达分组)

基础栅格 4px,仅允许以下档位:

Token值典型用途
--space-2xs4图标与文字、徽标内边距
--space-xs8控件之间、行内元素之间、按钮之间
--space-sm12控件与标签、内容区块之间、卡片内边距(紧凑)
--space-md16卡片 / 面板内边距、表面与内容
--space-lg24模块之间、分组之间
--space-xl32页面级分区

窗口内容边距:紧凑 16 / 常规 20。禁止 space-y-3/4/6 这类自由取值混用——统一走档位语义并在 lint 中校验。

层级值Tailwind适用
控件6pxrounded-md按钮、输入框、下拉、分段控件、开关轨、标签
容器8pxrounded-lg面板(Panel)、卡片、分组列表、对话框主体
浮层12pxrounded-xl菜单、下拉面板、Popover、Toast、Tooltip(大)
胶囊9999pxrounded-full徽标、头像、滑块柄

实现方式:把 --radius 设为 8px,shadcn 的派生规则即自动给出 md=6 / lg=8 / xl=12, 无需改动任何组件类名。除浮层外禁止使用 rounded-xl(lint 拦截)。

保留三档用户字号(根字号 13 / 14 / 15,--app-font-size),基准档 = 常规(14px)。

语义Token / Tailwind正常档小档大档对应
正文 / 列表主文本text-sm12.91213.8macOS Body 13 · Fluent Body 14
辅助文本 / 标签 / 说明text-xs11.81112.7macOS Subheadline 11 · Fluent Caption 12
页面 / 面板标题text-base141315macOS Title 3 15 · Fluent Body Strong 14
数值 / 等宽数据继承 + tabular-nums———表格、坐标、金额、时间
  • 行高:正文 1.5;标题 1.3;表格行 1.4。禁止任意行高值。
  • 字重:常规 400;次要强调 / 选中态 500;标题 600。禁止 700+。
  • 低于 12px 的正文字号一律禁止。
档位Tailwind小档(13)正常(14)大档(15)用途
紧凑h-722.7524.526.25工具栏 / 行内按钮、表格行内操作、小尺寸 Select
常规h-8262830表单控件、面板内动作按钮(默认)
提升h-929.2531.533.75主操作按钮、页面级输入(慎用)

高度一律用 rem 表达(随三档字号缩放),禁止写死 px。图标按钮尺寸与同档高度一致(size-7/8/9); 列表行高:紧凑 32 / 常规 36。

层次枚举(禁止 bg-muted/30、bg-muted/50、bg-muted/80 这类任意透明度):

层Token用途可否嵌套
basebg-background窗口底—
cardbg-card面板 / 卡片 / 分组列表可(一组相邻,不可叠同层)
raisedbg-popover浮层(菜单 / 弹窗 / Toast)浮于 base / card 之上
insetbg-muted输入槽、代码块底、只读区在 card 内使用
sunken--surface-sunken空态 / 占位底在 card 内使用
consolebg-console / text-console-foreground日志 / 终端输出独立区域,仅此一处深色
  • 一屏最多两级表面:base → card(+ 内部 inset)。禁止 card 套 card;需要子分组时用 分隔线 + 标题 + 间距。
  • 颜色语义:primary(accent)仅用于交互控件与选中态;destructive / success / warning / info 仅用于对应语义。同一颜色不得表达两种含义。
  • 半透明层上不放 accent 色(颜色放在实色层上,不放在毛玻璃前景)。
  • 唯一例外:首页 Hero 为品牌签名区,允许 primary 的低饱和装饰;除此之外不得用 accent 作装饰。
  • 所有边框 / 分隔线用 1px hairline(border = --border),不得混用 border-border(lint 拦截)。
  • 盒边框不叠盒边框:容器已有边框时,内部用 divide-y 或 border-t 分隔,不再画第二个盒子。
  • 表格:数据行用 divide-y(不用竖线);表头 border-b + 粘性;需要强调行时用斑马纹。
  • 聚焦态用 ring(§2.9),不通过改变边框颜色表达聚焦。
Token值对照用途
--dur-fast120msFluent 83mshover、按下、颜色 / 透明度变化
--dur-base200msFluent 167ms展开 / 收起、Tab 切换、Popover 进出
--dur-slow300msFluent 250ms对话框、页面切换、大面积材料进出
  • 缓动:进入 cubic-bezier(0.22, 1, 0.36, 1);退出 cubic-bezier(0.4, 0, 1, 1)。
  • 只动 transform 与 opacity(外加 backdrop-filter);不允许对 width / height / top / left 做动画。
  • prefers-reduced-motion: reduce → 位移 / 缩放改为 200ms 交叉淡入。
  • reka popper 定位容器的 transition-duration: 0s 例外必须保留(测量导致的漂移修复)。

可用区域仅限:侧栏、工具栏 / 标题栏、浮层(菜单 / 弹窗 / Toast / Tooltip)。 禁止:滚动内容区、表格、表单、卡片主体使用毛玻璃。

  • macOS → NSVisualEffectView 语义材质(见 macOS 平台层)。
  • Windows → Mica(窗口基底)/ Mica Alt / Acrylic(浮层)(见 Windows 平台层)。
  • 必须有纯色回退:prefers-reduced-transparency: reduce、用户关闭透明、Windows 电池节能 / 低端硬件 / 窗口失焦 → 回退为 bg-card / bg-background 实色。
  • 同一屏最多 2 处材质;禁止材质上叠材质;材质层主文本用 text-foreground(不用 text-muted-foreground)。
  • 焦点环(唯一写法):focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring/60, 形状跟随控件圆角;focus-visible 恒可见,不得 outline-none 后无替代(lint R6 拦截)。
  • 所有自定义可交互元素必须:可聚焦(tabindex="0")、有 role 与可读名称、响应 Enter/Space。
  • 复合控件键盘语义:分段控件 role="tablist" + ←/→;列表 / 表格行 ↑/↓ + Enter;菜单 / 下拉 ↑/↓ 循环、 Esc 关闭并归还焦点。
  • 全局快捷键:⌘, 设置 · ⌘K 命令面板 · ⌘F 页内搜索 · ⌘W 关闭窗口 · ⌘Z / ⇧⌘Z 撤销 / 重做 · ⌘1..9 切换侧栏分组 · Esc 关闭浮层。快捷键必须在界面可见。
  • 统一 @lucide/vue;尺寸仅 3 档:14(行内)/ 16(按钮、菜单)/ 20(工具栏、空态);描边宽度统一 2。
  • 与文字并排时用 gap-2,基线对齐。
  • 图标按钮必须有 aria-label + tooltip。
  • 图标不表达状态色,不叠加多个图标表达一个动作。

3. 组件语义(什么时候用哪个)

Section titled “3. 组件语义(什么时候用哪个)”
场景用什么不用什么
2–5 个互斥选项、需常显选择态分段控件(Segmented)一排开关、下拉
6+ 互斥选项 / 空间受限下拉(pop-up button)分段
细粒度布尔设置复选框(标题在右)开关
强调整组开关 / 重要开关开关(分组表单中用 mini 尺寸)复选框
数值微调输入框 + 步进(stepper)滑块
即时搜索 / 过滤SearchField(放大镜、清除按钮、输入即搜)普通输入框 + 按钮
不可撤销的危险操作Alert(默认按钮为安全项,破坏性项标红)普通确认弹窗、toast
可撤销的操作直接执行 + 状态提示(+ 撤销入口)弹窗确认
长任务(>1s)进度条 / 进度环 + 可取消转圈遮罩
页面级加载(>300ms 才有内容)骨架屏spinner 覆盖层
结果 / 日志类输出只读文本块(bg-console 仅日志)可编辑输入框

按钮层级:每个视图最多一个主按钮(default);其次 secondary;ghost 用于面板头部动作; destructive 仅用于破坏性操作且需 Alert 二次确认。

空态:图标(20)+ 一句主文案 + 一句说明 + 一个动作按钮;不出现空白页面。 加载态:<1s 不显示任何加载指示;1s–10s 用骨架屏或进度条;>10s 必须可取消并显示进度。 错误态(统一三分法):

场景呈现
表单 / 工具页内、可定位的错误就地进行:控件下方 text-xs text-destructive;多字段错误在页面顶部加一条错误条
当前操作失败但有明确重试入口工具页面板内的错误条(border-destructive/30 bg-destructive/10)+ 重试按钮
后台任务 / 系统级失败(无就地位置)toast.error(唯一允许用 toast 报错的场景)
成功不弹 toast:用状态变化表达;仅长任务完成可用 info toast

可恢复的提示用 info / warning 告警条,不用 toast。错误文案:说明发生了什么 + 下一步怎么办, 不道歉、不使用「出错了」。

  • 按钮用动词(保存、导出、重新选择),一个动作在流程中保持同名;按钮不带句号。
  • 打开浮层 / 对话框的按钮带省略号(更多选项…),立即执行的按钮不带。
  • 术语表:
用不用
工具 / 插件应用、功能模块
模块面板 / 面板卡片、区块
设置配置、偏好、选项页
导出 / 导入保存为、下载
工作表(Excel)sheet、页签
表头列名、header
  • 数字与单位:数字右对齐 + tabular-nums;单位与数字之间空格(5 MB);时间用 yyyy-MM-dd HH:mm。
  • 错误文案不道歉、不卖萌;占位文案说明「可以填什么」。

6. 反例清单(lint 会拦截其中可机器判定的项)

Section titled “6. 反例清单(lint 会拦截其中可机器判定的项)”
反例规范要求
两套卡片配方并存统一 rounded-lg border bg-card(§2.2 / §2.6)
任意透明度(bg-muted/30 等)走层次枚举(§2.5)
非浮层使用 rounded-xl仅浮层可用 xl(§2.2)
错误反馈混用三分法(§4)
键盘不可达自定义可交互元素必须可聚焦 + 有 role(§2.9)
手搓分段控件用 Segmented(§3)
图标按钮无提示必须 tooltip + aria-label(§2.10)
自由间距走间距档位(§2.1)
全局动效压制动效 token(§2.7)
卡片套卡片同一容器内用分隔线 + 标题 + 间距(§2.5)
  1. 新增 / 修改的视觉取值是否全部来自 token(无任意值、无写死 px)?
  2. 每屏是否最多两级表面(无卡片套卡片)?边框是否避免叠加?
  3. 每个模块是否都用 Panel(或平台等价容器)包裹,无裸露模块?
  4. 布尔 / 互斥选项的控件选型是否符合 §3?
  5. 加载 / 空 / 错误三态是否齐全,且错误呈现符合 §4 三分法?
  6. 键盘:Tab 顺序合理、焦点可见、Esc/Enter 语义正确、快捷键在界面可见?
  7. 图标按钮是否有 aria-label + tooltip?字形与尺寸是否取自三档?
  8. 文案是否符合 §5(动词、术语表、标点、单位)?
  9. 亮 / 暗、三档字号、窗口宽度 760 / 1080 / 1440 下是否都不破版?
  10. 平台差异是否只落在平台文档允许的差异点内(材质 / 窗壳 / 菜单 / 对话框语义 / 焦点视觉 / 半径)?