Files
WechatOnCloud/doc/dev/design.md
Gloridust 9981e9a5dc feat(design): 设计系统文档 doc/dev/design.md + 无障碍基线(焦点环/动效降级)
- doc/dev/design.md:把牛奶布艺设计语言正式沉淀为规范——设计哲学、令牌表(色彩/圆角/
  阴影高光/动效曲线,含深浅色)、布局与三 Tab 信息架构、逐组件规范(卡片/按钮三级/输入框/
  徽标体系/分段 Tab/折叠菜单/空状态/Toast/进度/模态)、动效、无障碍、文案、反例、落地清单。
  令牌与 class 名与 styles.css 一一对应,是可执行的活规范而非抽象理论。
- 无障碍基线(此前为 0):全局 :focus-visible 绿色焦点环(仅键盘导航出现,鼠标不触发;
  无边框拟物 UI 尤其需要);prefers-reduced-motion 降级(去装饰动效、保留 spinner/进度的
  必要循环)。已用真实构建 CSS 截图验证焦点环不被按钮 overflow:hidden 裁剪、贴合胶囊圆角。
2026-07-08 03:13:09 +08:00

10 KiB
Raw Permalink Blame History

设计规范 · 云微面板设计系统

本文是面板前端(panel/web)的设计语言与组件规范,与代码一一对应——令牌就是 styles.css 里的 CSS 变量,组件名就是真实的 class。改 UI 前先读这里;新增组件按此规范落地,别另起炉灶。 配套:架构层规范见 架构守则.md

一、设计哲学

三条主线,缺一不可:

  1. 牛奶布艺soft neumorphism —— 整个界面是盖在桌面上的一整块柔软白布,每个组件是被布从下方顶起的物体。这个比喻决定一切视觉:
    • 高光在物体顶面radial 渐变,中心偏上)——布料最贴、最受光处;
    • 阴影是布料折痕(小半径、紧贴边缘、冷灰蓝),不是悬浮投影
    • 组件亮度 背景(越靠近光源越亮);
    • 层级靠明度对比,不靠边框/分割线——全站几乎没有 border
  2. 微信绿主色 —— #07C160。主按钮、选中态、强调文字、焦点环都用它。用户对这个绿有肌肉记忆,别换色相。
  3. iOS 式饱满圆角 + 克制 —— 圆角只有大/中/小三档 + 胶囊;文案精炼、层级不超过 4 级字号。

一句话检验:任何新组件放上去,要像「同一块布下顶起的又一个物体」,而不是「贴上去的一张卡」。

二、设计令牌(:root,深色见 [data-theme='dark']

改样式只用令牌,不写死颜色/阴影。

色彩

令牌 浅色 深色 用途
--base #ebedf1 #14161c 整块布底色(页面背景)
--surface #ffffff #23262f 浮起表面(卡片/按钮 fill——必须 ≥ base 亮度
--trough #e0e3ea #0e0f14 凹槽(输入框/进度槽/折叠菜单条)——比 base 更暗
--text #1a1d24 #e7eaef 主文字
--muted #8a9099 #969ca6 次文字(最低到此级,不用三级灰
--wx-green / --wx-green-dark #07c160 / #06ad56 主色 / 主色按下态
--danger #fa5151 危险/离线/删除
--shadow 51 66 102(冷灰蓝) 0 0 0(近纯黑) 阴影色 RGBrgba(var(--shadow)/α)
--green-rgb / --danger-rgb 7 193 96 / 250 81 81 半透强调用

深色不是简单反色:base亮蓝黑surface 再高一档、阴影转近纯黑、顶面高光压到极淡0.06)。

圆角

令牌 用途
--r-card 28px 卡片、进入入口、模态
--r-blob 22px 中等浮起块
--r-small 16px 按钮、输入框
(胶囊) 999px 徽标 .tag、分段 Tab、chip

禁止直角或 <12px 小圆角——破坏「柔软布料」质感。

阴影与高光(布料的灵魂)

令牌 含义
--crease 浮起折痕(两层:0 1px 3px + 0 2px 8px,紧贴边缘)。所有浮起组件的基础
--crease-press 按下态折痕(更紧更浅)——按下即收紧,模拟按进布里
--crease-accent 绿色折痕(主按钮/Logo阴影色用 --green-rgb
--sheen 顶面高光 radialellipse at 50% 28%,白→透明)。所有浮起组件用 ::before 叠这层,否则变平贴色块

硬约束:阴影 x 恒为 0俯视对称光y ≤ 6第一层 radius ≤ 4、第二层 ≤ 14。radius >15 或 y >5 就成了悬浮投影,违反比喻。

动效曲线

  • 主 springcubic-bezier(0.2, 0.8, 0.2, 1),时长 0.160.2s按钮、输入聚焦、Tab。全站已用 12+ 处,别引入别的曲线。
  • Toast 入场:cubic-bezier(0.2, 0.9, 0.2, 1)0.32s。

三、布局与信息架构

  • 页面容器 .content:移动端 max-width:560px≥880px 宽屏 max-width:940px、加大内边距。始终居中。
  • 区块 .section-row(标题行,space-between,左标题右操作)+ .section-title15px/700。区块间距 margin-top:22px
  • 网格 .inst-gridrepeat(auto-fill, minmax(248px, 1fr))gap 14pxalign-items:start(各卡按内容高度,避免展开菜单时同行被拉等高)。
  • 三 Tab 信息架构(管理页):内容多时按用户心智分组成 Tab,而非一条长滚动。分组原则:
    • 日常高频(实例)/ 偶尔配置(用户)/ 出事才看(系统:残留资源+诊断+关于);
    • Tab 上用 .seg-dot 红点提示「该 Tab 有待处理事项」,避免藏进 Tab 的事被漏看;
    • 记住上次停留的 TabsessionStorage)。

四、组件规范

所有浮起组件 = surface fill + --crease + ::before--sheen。这是共用原子(.mf-raised.card/.enter-card/.list/.wx-state 共享)。

浮起卡片 .card / .inst-card

圆角 --r-cardpadding 1824pxoverflow:hidden::before 高光不外溢)。展开悬浮菜单时overflow:visible + 抬 z-index

按钮(三级 + 文本)

形态 用途
.btn surface 浮起 blob按下 scale(0.97) + 折痕收紧 次要动作
.btn.btn-primary 绿底、白字、--crease-accent、更克制的高光(别让白 sheen 冲淡绿) 主动作,一屏一个
.btn.btn-danger 红底,折痕用 danger 色 删除等破坏性动作
.btn-text 无浮起、绿字、按下淡绿底 行内轻操作(+新建、改名)

统一 height:48px--r-small。禁用 opacity:0.6、不改阴影。

输入框 .input(凹陷,不是浮起)

trough fill + 顶部内阴影inset),聚焦时叠 0 0 0 3px 绿色半透环。凹陷元素不画外折痕——它是被按进布里的槽,与浮起组件形成对比。

徽标体系 .tag(胶囊,white-space:nowrap

变体 语义
.tag(默认) 绿 中性/正向标识
.tag-on 绿 在线/正常
.tag-off 离线/已禁用
.tag-busy —— 处理中
.tag-warn 琥珀 可升级/需注意
.tag-muted 纯元数据(镜像版本号),tabular-nums

布局铁律:一个组件的标题行最多放 名字 + 1 个状态徽标。其余徽标(可升级、版本…)下沉到独立的 .inst-meta 元数据行(可换行)。塞多了就会名字被截断、徽标竖排——这是踩过的坑(见卡片布局修复)。

分段 Tab .seg-tabs / .seg-tab(凹槽 + 浮起选中胶囊)

外层 trough 凹槽胶囊(无外折痕),选中项是顶起的 surface 白胶囊--crease + 绿字)。这套「凹槽 + 浮起 bump」和输入框凹陷同构是本设计系统区分「选中/未选中」的标准范式。

理想增强:选中指示器用 matched-geometry「滑动」而非淡入淡出当前是 background 渐变过渡,可接受)。未来若做,用一个绝对定位的 bump + transform 过渡在选项间滑动。

折叠菜单 .inst-menu-toggle + .inst-menu

操作多时收进「管理」折叠菜单,按 运维/设置/危险 分组,危险项 .inst-menu-danger 单列。悬浮层不占文档流,点外部关闭。

空状态 .empty-state

中心 120px 的 surface 圆 blob.empty-blob + 折痕 + 高光)+ 图标ultraLight+ 标题 + 副标题 + 一个主按钮。别用一行冷冰冰的「暂无数据」。

Toast .toast / 进度条 .wx-progress

Toast 右上滑入(.toast-ok/.toast-error)。进度条:确定进度用 width%,不确定用 .indeterminate 循环。二者都是必要状态反馈,在 reduced-motion 下仍保留动画。

模态 .modal-mask + .modal

遮罩点击关闭(内容 stopPropagation.modal-actions 右对齐(取消在左、主/危险动作在右)。

五、动效规范

  • 状态切换用主 spring 曲线;Tab/分段切换倾向 matched-geometry 滑动而非淡入淡出。
  • 压按反馈:scale(0.97) + 折痕由 --crease--crease-press0.18s)。
  • prefers-reduced-motion: reduce:去掉装饰性过渡/位移,但保留 spinner 与不确定进度条的循环(否则像卡死)。已在 styles.css 末尾统一处理,新增装饰动画自动被覆盖。

六、无障碍(基线,不是可选项)

  • 键盘焦点环:全局 :focus-visible → 2px 绿色 outline + 2px offset。只在键盘导航时出现,鼠标点击不触发。无边框的拟物 UI 尤其需要它,否则键盘用户完全看不到焦点。输入框用自带内环、不叠加。
  • 对比度:文字最低到 --muted不用三级灰(亮白 surface 上会糊)。
  • 触摸目标:交互元素 ≥ 44×44按钮 48 高达标;小图标按钮注意留足点击区)。
  • 减弱动效:见上,尊重系统设置。

七、内容与文案

  • 全中文;语气像同事说人话,不像系统报错。错误给「怎么办」,不只给「出错了」。
  • 数字/版本号用 tabular-nums(对齐好看)。
  • 破坏性操作(删除/清数据)文案明确后果 + 二次确认,危险按钮红色。

八、常见错误(反例 → 正例)

大半径(>15+ 大 y 的 drop shadow 小半径紧贴边缘的 --crease 折痕
组件顶部 linear 渐变高光 中心偏上的 radial --sheen::before
用 border/分割线区分组件 靠明度surface > base > trough+ 折痕
组件 fill = base 或更暗 组件必须 --surface亮于 base
标题行塞名字+3 个徽标 标题行只留名字+1 状态徽标,其余进 .inst-meta
写死 #07c160 / box-shadow: ...黑 --wx-green / --crease 令牌
直角或 8px 小圆角 ≥16px 或胶囊
亮白 surface 上用三级灰文字 最低 --muted
无键盘焦点样式 全局 :focus-visible 绿环

九、落地清单(改/加 UI 前逐条过)

  • 只用令牌,没写死颜色/阴影/圆角;
  • 浮起组件有 surface fill + --crease + ::before--sheen
  • 阴影 x=0y≤6、无大散射;圆角 ≥16 或胶囊;
  • 组件亮度 ≥ base无 border/分割线;无三级灰文字;
  • 标题行 ≤ 名字 + 1 徽标,其余进元数据行;
  • 深浅色都过一遍(data-theme 切换);
  • 键盘 Tab 能看到焦点环;prefers-reduced-motion 下无眩晕动画;
  • 交互目标 ≥44px破坏性操作有确认 + 红色。