Skip to content

Latest commit

 

History

History
324 lines (256 loc) · 23.4 KB

File metadata and controls

324 lines (256 loc) · 23.4 KB

熵减 UI/UX 系统

本文档阐述熵减的 UI/UX 系统规格——组件、交互、布局、动效的参数与细则。 理念基线:theme.md(色彩与风格理念,本文档管「How」,theme.md 管「Why」)。 三段核心机制:相变资产(§二)· 思维显形(§三)· 语义排印(§四)——即 theme.md 三条「超越 Apple」思考的系统级实现。 状态:活跃(2026-08-24 建立)


一、布局与栅格

  • 间距网格:8px 基准(4px 半档仅用于图标内边距与微间距)
  • 桌面三栏结构:导航栏 240px(可折叠至 56px)· 列表栏 320–400px(可隐藏)· 主内容栏(限宽 720–900px 居中)
  • 窗口:最小 960×640;主窗口圆角由系统/外壳负责(Tauri 配置),应用内不模拟窗口装饰
  • 滚动:内容区滚动,侧栏/导航不随动;滚动条细样式(6px、悬停扩展)
┌──────────┬──────────────┬────────────────────────────┐
│ 导航 240  │ 列表 320–400  │ 主内容 720–900(居中)         │
│ (可折叠)   │ (可隐藏)      │                              │
└──────────┴──────────────┴────────────────────────────┘

二、相变资产(思考三:知识的凝固度可见)

2.1 四物态定义

物态 对应实体 特征
液态 视频/音频流、原始采集 模糊、流动、不可把握;圆角最大、无边框、低不透明度
半凝固 会话产物、提取中/沉淀中 影调渐显、边缘未定;中间态参数
固体 笔记(落库后) 纸面、硬边、可批注;标准卡片参数
晶体 闪卡、组(结算后) 同构网格、锐利、可组合;圆角最小、边框最强、阴影最淡

2.2 联变参数表(物态 → 视觉联合渐变)

参数 液态 半凝固 固体 晶体
圆角 20px 16px 12px 8px
背景 主题色 6% 透明 bg-sunken bg-surface bg-surface + 微渐变
边框 无 1px 虚线 --ed-border 1px 实线 --ed-border 1px 实线 --ed-primary 12%
内容影调 80% 透明 --ed-text-tertiary --ed-text-secondary --ed-text-primary
阴影 无 无 标准双层 标准双层(更淡)
出现动效 溶解 淡入 + 微位移 4px 标准入位 记忆浮现(仅晶体,见 §七)

2.3 应用场景

  • 会话里的一段转写:识别中=半凝固;会话结束落库=固体(可编辑)
  • 笔记转闪卡:草稿卡=固体;被首轮复习调度=晶体(进入组网格视图)
  • feed 碎片:导入时=半凝固;归组=固体;组结算后=晶体
  • 空状态/删除:反向相变(固体→半凝固→消失),与「不追债」哲学一致——删除体面,无确认弹窗惊扰

2.4 纪律

  • 相变是静默底层规则:用户感知「内容成型了」,但不感知「有渐变动效」
  • 相变不得用于装饰性组件(导航、按钮不入相变体系)
  • 四态参数只允许取表内值,禁止自定义中间态(防漂移)

三、思维显形(思考一:过程可见,而非结果可见)

3.1 处理态规范(替代所有 spinner/进度条)

处理 过程可视化 参数
ASR 流式转写 音频波形上,字词逐词点亮(随识别结果点亮,非弹字符) 点亮 150ms 淡入;已点亮的词保持 text-primary,未识别段 text-tertiary
OCR 检测 检测框逐个落定在画面(框线细 1px,落定后内容淡入) 框落定 200ms;全部落定后框线褪去 400ms
结构判定(四维解耦) 内容右上角微标注:结构 · 高 / 形态 · 教程(11px 标签,静默出现) 常驻但弱化;悬停显示判据原因
复习调度 卡片上的「下次复习」不是数字,而是24h 弧线刻度(刻度即时间点) 弧线 1.5px,当前时刻 = 刻度亮点(琥珀);悬停显示具体时间
AI 精修/知识补充 正文旁出现「增补」记号(琥珀下坠角标),正文以影调从浅入深完成 完成后角标保留 24h 后转为静默回链

3.2 时序与降级

  • 每个处理态自带内容:进度信息即内容本身,无空白等待页
  • prefers-reduced-motion:逐词点亮→整段淡入;框落定→一次淡入;弧线刻度不变(静态图形)
  • 禁用菊花转(spinner)于任何处理场景;长任务(>2s)允许「探针」式折线扫描(1.5px 线沿内容路径行进)

四、语义排印(思考二:内容自己说话)

4.1 内容语法表

语义 排印处理 示例
术语/关键概念 词重 500 + 0.05em 字距 生成效应
数值/时间戳 等宽 + tabular-nums 14:32:07 · 3,842 字
低置信内容 影调淡出(tertiary 或 opacity 70%) 转写错词、低置信 OCR 行
高置信结论 --ed-text-primary + 词重 500 提取出的结论块
来源回链(视频/画面) 脚注式:小一号 12px 下沉 + 琥珀「⨳ 回链」 ⨳ 04:32 · F·0071
代码/公式 等宽 + bg-sunken 内嵌块 FSRS::next
待办/行动 左缘 2px 靛蓝竖线 + 正文 动手闭环任务

4.2 排印规则

  • 同一条内容只允许命中最多两个语义(防花屏);冲突时优先级:置信度 > 来源 > 术语 > 数值
  • 转写流默认「无修饰」(正文同款),语义排印在会话终止/笔记落库时一次性应用——排印是「理解完成的标志」,不是实时装饰
  • 笔记页布局:主文 15/22 + 回链脚注下沉 + 术语上浮一档,形成「证据集」感

五、组件规格

组件 尺寸 圆角 状态要求
主按钮 高 36px(P)· 40px(L);内边距 16/20 8px default=靛蓝实底白字;hover=靛蓝 90%;active=scale 0.98;disabled=40% 透明;加载=左侧 16px 微型弧线
次级按钮 高 36px 8px 透明底 + --ed-border 1px;hover=accent 8% 底色
文本输入 高 36px 8px 常态=凹陷底无边框;focus=1px 靛蓝内框 + 焦点环;disabled=60%
卡片 内容自适应 12px(相变态按 §2.2) 常态带标准阴影;hover=阴影加深一档(不位移)
侧栏/浮窗 240px / 560px max 16px backdrop-blur 20px;浅 92% / 深 85% 透明
状态标签 高 22px 999px 文本 11px/500;底=accent 10% · 字=accent 深一档
列表行 高 44px 8px hover=bg-sunken;selected=靛蓝 8% 底 + 左缘 2px 靛蓝
空状态 图标 48px + 标题 17 + 说明 13 + 行动按钮 — 几何插画(靛蓝→琥珀柔渐变 60% 透明);文案=邀请行动
骨架屏 与内容同位 8px bg-sunken 微光扫过 1.2s/次;reduced-motion 静态

六、三时钟视图

视图 结构 规格
每日视图 任务队列(今日复习/待处理会话)+ 采集入口 标准密度;无叙事元素;办完即走;最大信息 1 屏
周报/月报 时间轴叙事:琥珀节点(进展)+ 靛蓝曲线(能力测量) 大留白;标题 28/34;无网格线;面积渐变 12%
事件视图 全屏 accent 柔光渐晕(8–12%)+ 单卡片 + 记忆浮现 只在事件时现身;平时不可见;一次性出现 6s 后卡片保留、渐晕退去

数据可视化风格:线 2px、无网格线、坐标轴 tertiary;平台期=虚线(停滞语义);突破=实线上折(靛蓝);记忆/证据点=琥珀实点。


七、动效规范

场景 时长 曲线 备注
hover/激活 120ms ease-out 仅底色/阴影变化
卡片/面板进出 200–250ms cubic-bezier(0.2,0,0,1) 位移 ≤8px
记忆浮现(签名) 400–600ms 同上 + blur(8px→0) 仅四场景:复习揭晓/结算报告/显影报告/回归之门
骨架/探针 — 循环 reduced-motion 静态
页面切换 150ms 交叉淡入 ease-out 不滑动(桌面工具定位,避免 iOS 化)

禁止:3D 翻转、弹性回弹(>1 次)、粒子、对用户输入的夸张响应。


八、图标语言

  • 线性 1.5–1.75px stroke、24px 网格、对齐整数坐标(视觉重量一致)
  • 语义图标(产品专有):提取(漏斗→卡片)· 显影(渐显矩形)· 复习(弧线+刻度)· 组(网格聚合)· 回溯(小回链箭头)
  • 状态图标:仅 16px(行内);颜色随语义(靛蓝/琥珀)

九、可及性

  • 对比度:正文 ≥ 4.5:1;大字/图标 ≥ 3:1(色板已校验;--ed-memory 琥珀在深色主题用亮化变体 #E8A04C 保证对比)
  • prefers-reduced-motion:按 §3.2 / §七 降级矩阵执行
  • 焦点:2px --ed-primary + 2px offset;列表行、卡片可独立聚焦
  • 颜色非唯一通道:影调+图标+文本三通道;低置信内容保证文本通道完整可读
  • 剪报底纹(--ed-mark-clip)上的文字只用 ink-3 及更深(--ed-ink-3 / --ed-ink-2 / --ed-ink-1);--ed-ink-4 禁止用于剪报底纹 —— --ed-ink-4 的 3:1 过渡态例外只在阅读面上成立,换到剪报底上亮档实测 2.8489、暗档 3.0480,连该例外都不满足
  • 文本缩放:rem 单位;200% 不破版(组件按内容自适应高度)
  • --ed-due 亮档第二次对比度修正(批 0-D,2026-09-11):#A05F10 → #9F5E10。触发底是剪报底纹这第三种底 —— --ed-due 要承载「记忆语义」文字(如「3 天后」),而旧值在剪报底上仅 4.4950:1,低于正文线。实测:剪报底 4.5571 / 纸 4.9309 / 面 5.1436(暗档 #E0A44B 不动,剪报底 7.4863 本就达标)。求解规则与余量要求见 ADR-033

十、Tokens 与主题(完整)

:root, [data-theme="light"] {
  /* 语义双色 */
  --ed-primary: #3B5BDB;   /* 熵减靛蓝:行动/聚焦 */
  --ed-memory:  #C77B2E;   /* 琥珀记忆:复习/沉淀/证据 */
  --ed-success: #2F9E44;
  --ed-danger:  #E03131;
  /* 中性灰阶(浅色·纸面) */
  --ed-bg-canvas: #F7F7F5;
  --ed-bg-surface: #FFFFFF;
  --ed-bg-sunken: #EFEFED;
  --ed-text-primary: #1A1A1A;
  --ed-text-secondary: #5C5C5A;
  --ed-text-tertiary: #949490;
  --ed-border: #E3E3E1;
  /* 形状/材质 */
  --ed-radius-control: 8px;
  --ed-radius-card: 12px;
  --ed-radius-panel: 16px;
  /* --ed-shadow-card 已被 --ed-shadow-1 取代(批 0-D Task 1 · 2026-09-11 用户裁决「纸感双层暖墨」):
     低层(菜单/浮层/小卡)= --ed-shadow-1;高层(Modal/浮窗)= --ed-shadow-2。旧值不再使用。 */
  --ed-shadow-1: 0 1px 2px rgba(28,25,23,.06), 0 4px 12px rgba(28,25,23,.08);
  --ed-shadow-2: 0 2px 4px rgba(28,25,23,.06), 0 12px 32px rgba(28,25,23,.14);
  --ed-blur: 20px;
  /* 动效 */
  --ed-ease: cubic-bezier(0.2, 0, 0, 1);
  --ed-dur-micro: 120ms;
  --ed-dur-card: 220ms;
  --ed-dur-reveal: 500ms;
}
[data-theme="dark"] {
  --ed-primary: #5C7CFA;
  --ed-memory:  #E8A04C;
  --ed-bg-canvas: #101013;
  --ed-bg-surface: #1C1C20;
  --ed-bg-sunken: #25252A;
  --ed-text-primary: #F2F2F0;
  --ed-text-secondary: #A0A09E;
  --ed-text-tertiary: #6A6A68;
  --ed-border: #2C2C30;
  /* 暗档做法已上升为 --ed-shadow-1/2 的统一策略:暗底不用投影(黑色投影不可见,只会让面板边缘糊成一团),改白色反相描边 */
  --ed-shadow-1: 0 0 0 1px rgba(255,255,255,.06);
  --ed-shadow-2: 0 0 0 1px rgba(255,255,255,.06);
}
@media (prefers-color-scheme: dark) { :root:not([data-theme="light"]) { /* 同深色块 */ } }

主题机制:显式 data-theme 优先,未显式时跟随系统偏好。切换时 200ms 交叉淡入。


十一、L1 原语层(批 0-D 落地 · ADR-033)

本节记录已落地的代码事实:app/src/ui/primitives/ 一个子域、41 个文件、唯一导出面 index.ts、逐个 ≤300 行。 数值真源一律是 app/src/ui/tokens.css 与 app/src/ui/primitives/motion.css;§五/§十 的旧目标态参数(靛蓝主色、8/12/16px 圆角、旧灰阶)仍是 2026-08-24 版本,待批 8 统一回写,不要以它们为准。 迁移在批 4(本批只交付靶子,界面外观零变化是设计意图)。

11.1 原语清单:用途 / 消费场景 / 禁止事项

原语 用途(一句话) 消费场景(批 4 迁移面) 禁止事项
Text 墨度 × 字阶的唯一出口 全部正文/标签/标题(现状 fontSize 1274 行 / 143 文件) 不做语义色决策(tone 只是「取哪一档墨度的名字」);不额外包裹 DOM;ink-4 是过渡态,不得承载唯一关键信息
Surface 面(底 / 边框 / 圆角 / 阴影)的唯一出口 卡片 / 列 / 阅读面 / 弹层底(现状 borderRadius 584 行、boxShadow 18 个不同字面值) 不承载排版(属 Text);interactive 只给视觉,键盘可达性由消费方用真实 <button>/<a> 承载
Button 四态契约的唯一出口(hover / active / focus-visible / disabled+busy) 121 个文件的按钮与 60 个文件的按钮样式常量 无 danger 变体、绝不用 --ed-stamp;不覆写 tabIndex/role;危险语义用 ConfirmDialog
Modal 弹层唯一实现(createPortal + role="dialog" + aria-modal + 焦点陷阱 + ESC 栈) 28 个手写弹层 消费者不得自建第二套 Portal / 焦点陷阱 / ESC 监听
ConfirmDialog 危险确认(印章标记 + 级联影响清单) 23 处 window.confirm / 裸 confirm( 确认按钮保持中性(variant="secondary");级联一律不给撤销(只给确认)
Toast 进出场 180/140 + 可打断(新消息接管,不排队) 4 套自绘 toast(现状全部只有进、没有出) 不排队;action 点击后不自动消失;只有 err 用 aria-live="assertive"
EmptyState 空态三段槽位 + 主行动按钮 40 行 / 28 文件的「暂无…」灰字(5 套空态) 不设 role;装饰图标不给 label;不加 className/style(空态是「一处的形态」)
Loading / Skeleton / Probe 加载三形态:形状已知 → 骨架;要一句文字 → 加载;都不要 → 探针 85 处 / 30 文件的手写灰字 不写字号与颜色(排版属 Text);Probe 恒为装饰(aria-hidden);需要被朗读的加载态不许用 Probe
StatusLine 错误 / 警告 / 成功 / 信息四档语义的唯一出口 196 处 / 76 文件(三种红并存) 本原语不渲染任何按钮(action 是纯插槽);颜色不是唯一信号 —— 「这是什么」必须由 children 的文字说清
z-index 六档标尺(批 0-A) 叠放顺序的唯一来源 32 文件 45 处硬编码(17 个不同值) 不写裸数字(一律 zIndex("modal" | "modalNested" | "toast"));迁移必须按叠放段整段推进

11.2 交互态契约(本批从零建立)

  • 承载方式 = CSS 类(.ed-<原语> + --<档> 修饰类 + -<部位>/__<部位> 子元素类),不是内联 style: :hover / :active / :focus-visible / @keyframes / @media (prefers-reduced-motion) 都无法内联表达。
  • 四态:hover(Button 三档各异、Surface--interactive 升起 --ed-shadow-1 + translateY(-1px))· active(按下微陷 1px)· focus-visible(2px --ed-ink-1 焦点环 + 2px offset;鼠标点击不留环、键盘 Tab 必须可见)· disabled / busy(cursor: not-allowed + opacity: .55;disabled 移出 Tab 序,busy 保留焦点与 Tab 序)。
  • 墨度即确定度:Text 的 tone 九档;任何交互(悬停/聚焦/选中)立即升到正文墨度(§4.3 规则 2)。
  • 出现场:Modal/ConfirmDialog/Toast 一律走 [data-phase] 三态(enter / entered / exit), 退场期禁用指针事件(见 11.3)。

11.3 动效接缝与 prefers-reduced-motion 承诺

  • 一处改对所有地方:所有时长/缓动只经 var(--ed-dur-*, 同值字面量) / var(--ed-ease, …) 消费,变量块在 motion.css 一处定义(真源属批 6,届时整块删除即生效,无需改任何规则)。
  • 接缝锚点:Button/Surface 的四态类 · Text 的墨度与字距 transition · Modal/Toast 的 [data-phase] · EmptyState 的 .ed-empty-enter · Loading 的 ed-skeleton-shimmer / ed-probe-swing(循环环境动效走 CSS @keyframes)· StatusLine 的一次性浮现过渡。
  • 无障碍优先:app/src 内唯一一条 prefers-reduced-motion 块在 motion.css,覆盖全部 .ed-* 基类 与每一处 animation 声明的选择器原文(含伪元素)(transition 与 animation 双双压到 1ms)。新原语只要根类进名单 就自动被覆盖 —— 这是规格 §11 验收 5「覆盖率 100%」的判据,由 motion-coverage.test.ts 机器守门 (判据 = 基类名单 + 动画落点名单,不是「全类集合 ⊇」:.ed-modal-head/body/foot、.ed-confirm-seal/-impacts/-keep、 .ed-empty__title、.ed-toast-action 这些子元素类与基类同在一个元素上,逐字枚举只会假红)。 ⚠️ 伪元素必须逐字列出:animation-duration / animation-iteration-count 不是可继承属性,覆盖写在宿主元素上 伪元素拿不到 —— T11 评审用 headless Chromium 实测:.ed-skeleton 已静止而 .ed-skeleton::after 仍是 1.2s / infinite。
  • keyframes 只用于「循环环境动效」(Loading 的骨架微光 / 探针);EmptyState 的入场(.ed-empty-enter)与 StatusLine 的浮现都走一次性 transition,状态行不做循环动画(它是信息不是「呼吸物」,循环会在长列表里变成噪音)。
  • 可中断、可反向:usePresence 的退场途中 open 回 true ⇒ 清计时器、直回 entered(不重放进场);Toast 的新消息接管而非排队。
  • 位移上限 8px(规格 §8.4):原语层任何位移 ≤8px,批 6 的 GSAP 时间线同样不得越过(机器判据在 style-seams.test.ts)。

11.4 token 消费纪律与两条用色禁令

  • 原语只许用 var(--ed-*) 与 zIndex();primitives/**/*.css 内零颜色字面量(色值只在 app/scripts/gen-tokens.mjs 与产物 tokens.css)。z-index 用 TS 标尺,不作 CSS 变量。
  • 禁令一(危险色):--ed-stamp 是全站唯一非中性色,绝不用于按钮,也不得出现在任何 background* 声明里 —— 它只做文字色(StatusLine.error、Text tone="stamp"、ConfirmDialog 的印章)与描边 (ConfirmDialog 印章边框、Toast--err 的左边框)。按钮一律中性。反例守卫在 style-seams.test.ts。
  • 禁令二(剪报底纹):剪报底纹上只用 ink-3 及更深(§九同款条款);--ed-ink-4 禁止用于剪报底纹。

十二、审校模式(阅读面墨度加深)

依据:规格 §4.3 条件 ③「进入审校模式时全部升到 ≥4.5:1」与该节的就地加注(批 4 / 批 6 / 批 7 / 批 8 T3)。 本节写的是规范面(用户看到的审校模式是什么);🔴 实现落点登记在 12.2 末条(它不是生成物 ui/tokens.css)。

12.1 定义

  • 入口:顶栏右簇的一个可发现按钮(与 ⌘K / ⚙ 齿轮同簇),加快捷键 ⌘/Ctrl+Shift+R。按钮必须带 可读文案 + 快捷键提示(title)—— 「可发现」是条件 ① 的字面要求,不靠用户猜快捷键。 ⚠️ 入口不进视图注册表:它不是第四种「视图」,而是所有视图共同的面(规格 §4.3① 逐字)。
  • 作用域:当前阅读面的全部文本节点(NotesReadingColumn 的每一种视图、卡片流行、印样正文); 不含编辑器(RichEditorView)与弹层外的外壳 —— 编辑态已有自己的墨度语义。切到别的对象 ⇒ 模式保持 (它是「我此刻在审读」的用户意图),但只影响当前挂载的阅读面。
  • 三出口(等价):再按同一个快捷键 · 点同一个入口按钮 · Esc。三条都必须能出; 退出后墨度立即回到未进入前的档位(不得留任何中间态)。
  • 缺省不落属性:常态下 <html> 上没有这个属性;退出走 removeAttribute,不是写成 "off" —— 否则「缺省态」与「显式关」在 DOM 上不可分,首屏还白多一个属性。

12.2 载体与取值

  • 载体 = <html> 根元素上的 data-* 属性(与 data-theme / data-motion / data-shell-phase 同范式), 不是类名(规格 §8.3 逐字:载体 = data-*,禁止用类名区分)。
  • 属性名 data-proofread-mode,取值 "on"(缺省 = 不落属性)。🔴 命名消歧:proofread 一名已被 LLM 文本校对占用(commands_proofread.rs / ProofreadPanel.tsx)⇒ 本模式必须用 data-proofread-mode, 不得用 data-proofread(控制方 §2 B2;规格 §4.3④ 原文的三处写法由紧邻的就地加注改读)。
  • 🔴 不新增 token:审校模式不是第五档墨度,而是档位覆盖 —— 模式位下把 --ed-ink-4 的值重绑到 --ed-ink-3,.ed-text--ink-4 的规则一个字不改 ⇒「全部升到 ≥4.5:1」由变量重绑一次兑现, 调用点零改动、零逐处判断(规格 §4.3⑤ 的机制不变,只更正落点)。暗档同样被覆盖(变量重绑一次通吃)。
  • 模式位的单一写入方:useProofreadMode() 在生产里只许调用一处(App.tsx,第二、三出口的宿主), 其他面(含顶栏入口按钮)必须复用同一份状态(经 props / context 注入)—— 属性是全局唯一的载体, 两处各持一份 state 必然互擦(判据见 shell/proofreadMode.dom.test.tsx 的「单一写入方」用例)。
  • 🔴 本节登记:实现落点 = app/src/ui/proofread.css(由 main.tsx 在 token CSS 之后 import), 不是生成物 app/src/ui/tokens.css(:2-3 逐字「由 scripts/gen-tokens.mjs 生成,请勿手改。手改会被 src/ui/tokens.drift.test.ts 判失败」)⇒ 不得手改生成物,也不得改生成器 gen-tokens.mjs 与 ui/primitives/Text.css(控制方 §2 B1)。
  • 落地状态(带时点,2026-09-13):① 模式位(shell/proofreadMode.ts)· ② 纯 CSS 覆盖 (ui/proofread.css)· ③ 快捷键与 Esc 两条出口(App.tsx)已入库(批 8 T9); ④ 顶栏入口按钮已落地(批 8 T11):位置 = 顶栏右簇的 topbar-proofread(复用右簇动作按钮族,零新样式常量), 状态由 App.tsx 透传同一份模式位(单一写入方)⇒ 按钮 / 快捷键 / Esc 三条出口合流。

本文档与 theme.md 同步维护(2026-08-24 建立)。组件/参数变更须回写本文档。