通用 GUI 与直接操作设计规范
面向设计师与工程师:图形界面让人相信"我看到的就是那个东西,我动它它就会变"。这份规范规定的不是控件长什么样,而是让这个信念成立所必须兑现的条件——对象可指认、后果可预知、变化可撤回、状态说得出真假、换一只手也能做完、还没提交的东西不会消失。
6 条原则 · 38 条规则 · 必须 31 · 应当 7
目录
面向设计师与工程师:图形界面让人相信"我看到的就是那个东西,我动它它就会变"。这份规范规定的不是控件长什么样,而是让这个信念成立所必须兑现的条件——对象可指认、后果可预知、变化可撤回、状态说得出真假、换一只手也能做完、还没提交的东西不会消失。
图形界面产品做的是同一件事的两半:把系统内部的状态显示成用户可以指认的对象,再把用户对这些对象的动作翻译回系统内部的改变。直接操作(direct manipulation)之所以好用,是因为这两半之间的距离足够短——看见的就是可操作的,动作的结果立刻可见,做错了可以退回去。这个领域最常见的设计错误,是把"看起来像直接操作"当成了"是直接操作":界面上的方块动了,服务端还没收到;灰掉的按钮说不出为什么灰;选中了十七个对象但屏幕上只看得见三个;拖动是唯一能改顺序的办法;提交失败之后表单清空重填。这些都不是控件做得不好看,而是这个界面对用户作出的承诺没有兑现。
本规范由六条原则和 38 条规则组成:原则说明设计方向,规则规定适用情境、行为要求与验证方式。每条规则归属且仅归属一条原则,规则编号即原则编号(UI3-2 就是第三条原则下的第二条规则)。
原则按规范对象切分,而不是按界面区域或控件类别切分。理由是:同一个控件在不同时刻承担完全不同的义务——一个"删除"按钮在被点之前属于对象的可操作性问题(能不能点、为什么不能点),在被点的瞬间属于后果与可逆性问题(会删掉哪些、能不能撤回),在被点之后属于反馈问题(受理了没有、成功了没有),而它在触屏与键盘下是否都能到达则属于输入对等问题。按控件切分会把这四种义务混成一条"删除按钮规范",按对象切分才能让每种义务各自可验证。
适用范围:以窗口、页面、表单、列表或画布承载对象操作的 Web、桌面与移动端产品。规范规定对象、动作、反馈、输入、录入与操纵的行为要求,不指定视觉风格、组件 API 或实现框架。没有拖放、批量或远端写入的界面,可将对应条款记录为不适用;不能把缺少实现写成不适用。
每条规则都应形成三项可审查的交付:设计决定、机制事实、用户反馈。例如“提交失败保留输入”,要同时说明保留哪些字段、系统从哪里恢复、用户如何继续。仅画出成功态或填完参数不能证明承诺成立。
全文四章:第 1 章原则,第 2 章规则的读法与速查,第 3 章规则详解,第 4 章术语;验证清单、论据说明和最小设计记录见附录 A、B、C,完整来源见 reference.md,可配置项见《通用 GUI 与直接操作 Design Token》。
1. 六条原则
六条原则按规范对象切分设计责任:每条原则管辖一类对象上的义务,每条规则按其义务的直接规范对象归属唯一原则。对象不同,原则就不会互相替代——这是切分的依据,也是检验切分的方式。
| 原则 | 规范对象 | 设计方向 | 管辖规则 |
|---|---|---|---|
| UI1 对象可指认 | 界面中被操作的对象及其当前状态 | 用户操作的是可指认的东西,不是猜出来的东西。什么可操作、当前选中什么、为什么现在不能操作,都必须可见 | UI1-1 ~ UI1-6 |
| UI2 后果可预知可撤回 | 一次操作的后果及其可逆性 | 在按下之前知道会发生什么,在按下之后能退回去。撤销是默认能力,不是补救措施 | UI2-1 ~ UI2-6 |
| UI3 状态与反馈可见 | 系统对一次操作作出的回应与运行状态 | 受理、进行中、完成、失败是四件事。界面变了不等于事情成了 | UI3-1 ~ UI3-6 |
| UI4 输入方式对等 | 用户可用的输入设备与操作通道 | 完整支持覆盖全部核心任务,限定支持说明子集。对等的是任务,不是手势 | UI4-1 ~ UI4-7 |
| UI5 录入是一类承诺 | 用户已输入但尚未提交的内容 | 人写下的东西不因系统的行为消失;判错要判得是时候,说错要说得出怎么改 | UI5-1 ~ UI5-7 |
| UI6 直接操纵有等价路径 | 拖放及其他连续操纵动作 | 连续动作是一种输入方式,不是一项功能。功能必须在没有这种动作时依然存在 | UI6-1 ~ UI6-6 |
同一个场景可以触及多条原则——用户框选二十个文件、拖进另一个文件夹、松手后看到进度条、中途网络失败——这一步同时面对选区所指对象是否可核对(UI1-4)、跨容器是移动还是复制(UI6-3)、批量结果能否逐对象报告(UI3-5)、以及部分失败之后能否整体撤回(UI2-6)。这不是分类错误:四条规则约束的是四个不同规范对象上的义务,一个是选区,一个是操纵语义,一个是反馈,一个是可逆性。互斥与穷尽是这套切分接受检验的主张,不是宣布即成立的事实:规则增删或归属存疑时,按附录 A 的分类检验验证。检验不过,修改的是原则的切分。
本切分中最需要持续检验的两处边界,在此明示:UI1 与 UI3——UI1 管对象自身的状态(这个东西是什么、能不能动、是不是被选中了),UI3 管系统对一次动作的回应(收到了没有、进行到哪了、成了还是败了)。按钮变灰归 UI1,按钮转圈归 UI3;"为什么不能点"归 UI1-3,"点了之后怎么样"归 UI3-2。UI4 与 UI6——UI4 管的是产品声明支持哪些输入方式、这些方式能否完成核心任务,UI6 管的是连续操纵这一类动作自身的语义与替代。"拖放必须有非拖放等价路径"的直接规范对象是拖放这个操纵,因此归 UI6;"同一个任务在键盘、触屏与手柄下都能完成"的直接规范对象是输入方式的承诺范围,因此归 UI4。这两处若在实践中反复出现归属争议,应当调整原则而不是增设中间层。
原则用于理解规则与裁决归属,本身不作为单独的判定条目。当原则与具体条款的解读出现冲突时,以适用条款为准,并记录需要澄清的歧义。
规则归属唯一,不等于机制不能复用。一套"对象身份"既是选区在视图变化后存续的依据(UI1-5),也是撤销定位到具体对象的依据(UI2-3),还是批量失败报告能指名道姓的前提(UI3-5);一份"不可逆操作清单"既决定确认档位(UI2-4),也决定乐观更新是否可用(UI3-4)。同一机制一物多用是常态,写在哪条取决于义务的直接规范对象。
2. 规则的读法
2.1 每条规则的结构
| 部分 | 作用 |
|---|---|
| 一句话 | 规则的记忆版,不替代正文 |
| 适用 | 这条规则在什么情境下生效。不落在适用范围内的产品记录"不适用"即可,不必勉强套用 |
| 规则 | 规范正文,规定这条规则的要求 |
| 边界条件 | 与适用共同限定要求的适用范围:说明这条规则不要求什么、例外在什么条件下成立(仅部分规则有) |
| 设计应用 / 验证示例 / 反例 | 帮助落地的说明,不另行增加义务,也不指定唯一实现 |
| 依据与参考 | 失败记录与实现参考(仅部分规则有;论据类型与出处见附录 B 与 reference.md) |
一句话概括各部分的效力:规则正文规定要求;适用与边界条件共同限定要求的适用范围;设计应用、验证示例、反例与依据参考不另行增加义务。
规则写行为性质、不写实现方式:一次操作的作用对象在提交前可核对,这是产品行为;用计数徽标、可展开清单还是二次页面呈现它,是设计方案——两者必须对得上,但不是同一份交付物。
2.2 约束词
规则正文使用三级约束词:
- 必须:不满足即不符合本规范。缺了它,某条对用户的承诺会在可预见的情境下失效——这是标「必须」的唯一依据。
- 禁止:与「必须」同等强度的反向表述,指明不得出现的行为;正文中的「不得」与「禁止」等价。
- 应当:默认遵循;确有理由偏离时,记录理由与替代做法,并接受同样的验证。偏离不需要审批,但需要留痕。「不应当」是「应当」的反向表述。
合规判定以正文中的独立义务子句为单位:无约束词的陈述句承接所在规则标题的强度;显式标注约束词的子句按其自身强度判定——【应当】规则内的「禁止/不得」子句仍是硬约束(UI1-6、UI2-5、UI3-3、UI3-6、UI4-5、UI5-5、UI6-6 含此类子句),规则标题与速查表的强度标注不替代子句约束力。正文中的「不能」仅用于能力或事实陈述,不表达义务。
强度表示约束力,不表示重要性。
2.3 反例的两侧
反例分两侧:"做不到"是漏掉这条要求,"做过头"是为了满足它而在每个动作前加确认、在每个字段旁挂说明、把每次点击都变成一次审批。两侧都算没做对。通用 GUI 被做坏的方式在两端都很密集:一端是界面上什么都在动、什么都说不清——灰掉的按钮不说为什么灰,删除之后没有撤销,提交失败之后表单清空;另一端是把谨慎堆在用户身上——每删一行都弹一次确认、每个输入框刚打第一个字就标红、每次离开页面都拦一下不管有没有改过东西。前一端让人不敢动,后一端让人学会闭着眼睛点"确定",而后者恰恰会让真正重要的那次确认失效。克制不等于含糊,谨慎不等于把判断推给用户。
2.4 规则速查:38 条
下表是全部规则的一句话记忆版,点击规则名可跳到第 3 章的完整正文。速查不替代各条的适用条件与完整要求;个别【应当】规则内含禁止级子句(UI1-6、UI2-5、UI3-3、UI3-6、UI4-5、UI5-5、UI6-6),判定以正文为准(见 2.2)。
UI1 对象可指认
| 规则 | 强度 | 一句话 |
|---|---|---|
| UI1-1 操作有明确的作用对象 | 必须 | 每条命令都说得出它动的是哪个东西。 |
| UI1-2 可操作性可感知 | 必须 | 能不能点,看出来,不是试出来。 |
| UI1-3 不可用状态说明原因与恢复条件 | 必须 | 灰掉不是终点,得说为什么灰、怎么才能不灰。 |
| UI1-4 选区是产品对象 | 必须 | 当前选了哪些,用户动手前要能核对。 |
| UI1-5 视图变化后选区保持或明确失效 | 必须 | 排序筛选之后,选中的还是刚才那些东西。 |
| UI1-6 焦点、悬停与选中分别表达 | 应当 | 光标在哪、鼠标在哪、选中的是哪,是三件事。 |
UI2 后果可预知可撤回
| 规则 | 强度 | 一句话 |
|---|---|---|
| UI2-1 提交前可知后果 | 必须 | 动多少东西、能不能退回来,按下之前就该知道。 |
| UI2-2 撤销优先于确认 | 必须 | 低后果操作用撤销减轻打断,重要后果仍需相称确认。 |
| UI2-3 撤销边界对齐用户心智 | 必须 | 一次撤销撤掉用户认为的那一步。 |
| UI2-4 不可逆操作按后果分级 | 必须 | 确认的强度由后果决定,不由弹窗数量决定。 |
| UI2-5 破坏性动作不设默认执行 | 应当 | 手滑的那一下,不该正好落在最狠的选项上。 |
| UI2-6 撤销失败如实说明并给出补救 | 必须 | 没撤回来就别说已撤回。 |
UI3 状态与反馈可见
| 规则 | 强度 | 一句话 |
|---|---|---|
| UI3-1 操作被受理有即时反馈 | 必须 | 先让人知道"它听见了"。 |
| UI3-2 阶段、结果与未知分别可辨 | 必须 | 已接收不等于已完成,未收到结果也不等于失败。 |
| UI3-3 进行中给出可判断的信息 | 应当 | 能不能取消、要不要等,比进度条本身更有用。 |
| UI3-4 乐观更新须可回滚且回滚可见 | 必须 | 先显示后确认可以,失败了偷偷改回去不行。 |
| UI3-5 失败可定位到对象与原因 | 必须 | 二十个里坏了三个,就得说是哪三个。 |
| UI3-6 反馈的存续时间不构成操作期限 | 应当 | 撤销入口不该跟着提示一起消失。 |
UI4 输入方式对等
| 规则 | 强度 | 一句话 |
|---|---|---|
| UI4-1 核心任务在每种声明支持的输入方式下可完成 | 必须 | 对等的是任务,不是手势。 |
| UI4-2 悬停与上下文菜单不作为唯一入口 | 必须 | 触屏上没有悬停,那些功能不能就此消失。 |
| UI4-3 切换输入方式不重置工作状态 | 必须 | 放下鼠标拿起键盘,选区和草稿还在。 |
| UI4-4 靶区与精度要求可测量 | 必须 | 测的是能点中的范围,不只是图标有多大。 |
| UI4-5 输入能力差异明示而非静默降级 | 应当 | 做不到就说做不到,并给一条别的路。 |
| UI4-6 图形层不阻断键盘与辅助技术路径 | 必须 | 自定义控件和拖放实现,不能把路堵死。 |
| UI4-7 指针动作可在提交前取消 | 必须 | 按错能移开,取消不提交。 |
UI5 录入是一类承诺
| 规则 | 强度 | 一句话 |
|---|---|---|
| UI5-1 未提交的内容不因系统行为丢失 | 必须 | 人写下的东西,不该被刷新一下带走。 |
| UI5-2 校验时机与错误位置对齐输入过程 | 必须 | 别在人还没写完的时候说他写错了。 |
| UI5-3 错误信息说明如何改对 | 必须 | "格式不正确"没有告诉任何人该怎么办。 |
| UI5-4 提交失败保留已输入内容 | 必须 | 系统的失败不该由用户重打一遍来赔。 |
| UI5-5 离开确认以实质变更为条件 | 应当 | 没改过东西就别拦,拦了就要说清丢什么。 |
| UI5-6 自动保存与业务提交语义分开 | 必须 | "已保存"到底指哪一层,要说得出来。 |
| UI5-7 输入辅助与组合输入不中断 | 必须 | 选词不提交,粘贴与自动填充可用。 |
UI6 直接操纵有等价路径
| 规则 | 强度 | 一句话 |
|---|---|---|
| UI6-1 拖放有非拖放的等价路径 | 必须 | 拖不动的人,也得能把这件事做完。 |
| UI6-2 投放目标与结果在松手前可见 | 必须 | 放下之前就知道会放成什么样。 |
| UI6-3 跨容器是移动还是复制须明示 | 必须 | 拖过去之后原处还剩不剩,不能靠猜。 |
| UI6-4 一次操纵作为一步被撤销 | 必须 | 拖错了按一次撤销就回来,不是按五次。 |
| UI6-5 中途放弃不留部分结果 | 必须 | 取消当前操纵,不留下这次动作的半成品。 |
| UI6-6 精度要求与输入方式相称 | 应当 | 要对齐到像素的事,别只让手去稳。 |
3. 规则详解
本章按六条原则展开全部 38 条规则。每条的结构与各部分的约束力见 2.1;其中的设计应用、验证示例与反例只是帮助落地的说明,不指定唯一组件,也不要求新增独立交付文档。
3.1 UI1 对象可指认
直接操作的前提是界面上存在可以指认的对象:用户看得出它是什么、能不能动它、现在有没有把它选上。这条原则管的是对象自身的状态如何被表达,以及一条命令与它的作用对象之间的对应关系如何成立。它不管命令做完之后发生了什么——那是 UI2 与 UI3 的事。本原则的核心主张是:可见性不蕴含可操作性,可操作性不蕴含当前可用,而"当前选中了什么"是一个必须被显式维护的产品状态,不是控件的内部变量。
UI1-1操作有明确的作用对象必须
一句话:每条命令都说得出它动的是哪个东西。
适用任何提供图形界面并允许用户对界面元素下达命令的产品。
规则每一次可发起的操作,其作用对象必须在发起前可解析到具体对象或对象集合,并可向用户呈现。对象必须具有在刷新、排序、筛选与分页之后仍然稳定的身份(见 gui.object.identity.key);禁止以屏幕位置、行序号或"最近点过的那个"作为对象身份。当一条命令的作用对象随界面上下文变化时,当前所指对象必须与命令入口同时可见。
边界条件本条不要求为每个操作都显示对象名称。作用对象与命令入口在空间上直接相邻且无歧义时(在一行内的删除按钮),相邻本身即构成呈现。本条也不要求对象是数据库实体——一段选中的文字、一个未保存的画布区域同样是对象。
设计应用把"当前作用对象"作为一个显式的界面状态来维护,而不是在点击时才现场推断。同一命令从工具栏、菜单、快捷键与右键进入时,作用域必须与入口声明一致。右键针对单项、工具栏针对选区可以并存,但不能只凭未说明的输入方式改变作用对象。
验证示例
- 用户侧:从工具栏、右键菜单与快捷键三条路径发起同一操作,检查作用对象是否符合各入口明确表达的范围。
- 实现侧:检查命令处理是否依赖对象身份而非列表下标;构造一次排序后重放同一命令,观察是否作用到了另一个对象。
反例做不到——列表刷新后按下"删除",删掉的是排到那个位置上的另一条记录;做过头——每个按钮旁边都重复打印一遍对象全名与标识符,界面被身份信息填满。
依据与参考直接操作把命令与对象的对应关系放在界面上而不是命令语法里,这是该交互范式的基本主张(R01);把关注的对象持续呈现出来、让界面动作贴近任务本身,是"直接"得以成立的机制(R03)。
UI1-2可操作性可感知必须
一句话:能不能点,看出来,不是试出来。
适用界面中同时存在可操作元素与不可操作元素的产品。
规则可操作的元素必须由感知线索与不可操作的内容区分开,且该区分在产品声明支持的每种输入方式下成立(见 gui.input.methods)。禁止把"仅在悬停时出现"作为可操作性的唯一线索。可操作性线索必须与元素的实际可用状态一致:看起来能点却点了没反应,与看起来不能点却其实能点,同属本条的违反。
边界条件本条不规定用什么线索,也不要求所有可操作元素采用同一种线索。刻意的探索式界面(游戏、创意工具中的隐藏交互)可在声明该设计意图并保证核心任务另有可见入口的前提下偏离,但完成核心任务所需的入口不适用该例外。
设计应用把"这个元素可操作"与"这个元素现在可用"设计成两个独立的表达维度;前者稳定,后者随状态变化。密度很高的界面容易退化为"全靠悬停",此时应当检查:把鼠标拿开之后,用户还能不能看出哪些地方能动。
验证示例
- 用户侧:在触屏与键盘遍历两种条件下截图,检查可操作元素是否仍可辨识。
- 实现侧:禁用全部悬停样式后渲染界面,核对可操作元素的可辨识性是否明显下降。
反例做不到——表格行末的操作按钮只有鼠标移上去才出现,触屏用户找不到;做过头——把每个可点区域都加上边框、阴影与图标,正文里的每个词都像按钮。
依据与参考可感知的可操作性属于"系统状态可见"的一部分(R04);不依赖单一输入通道承载关键命令,在平台输入指南与无障碍标准中均有对应表述(R07、R12)。
UI1-3不可用状态说明原因与恢复条件必须
一句话:灰掉不是终点,得说为什么灰、怎么才能不灰。
适用会把操作或对象置为不可用、只读或受限状态的产品。
规则对象或操作处于不可用状态时,系统必须让用户可以获知不可用的原因与恢复条件;禁止只呈现不可用状态而不提供任何解释路径。呈现给用户的原因与实际执行拦截的判定必须来自同一处(见 gui.object.unavailable.reason.source),不得由界面另行编写一套解释。不同成因须可区分:内容只读、权限不足、当前状态不允许、能力不支持、配额或期限限制的恢复路径互不相同(见 gui.object.restriction.kind)。
边界条件本条不要求把原因常驻显示,按需可查(提示、说明入口、点击后的解释)即满足。原因本身对用户不可行动且已记录理由时(出于安全考虑不披露具体权限判定),可只说明该操作在当前身份下不可用并给出求助路径,这属于本条允许的取值而非默认取值。本条不要求把不可用的对象一律显示出来——不显示也是合法选择(见 gui.object.unavailable.mode),但一旦显示,就要说得出来。
设计应用把"为什么不可用"当成一条与拦截逻辑共享判定的数据,而不是一句写死的文案。多个条件同时不满足时,优先说明用户当前能改变的那一个。
验证示例
- 用户侧:对每一类不可用状态,检查用户能否在不联系支持的情况下知道下一步做什么。
- 实现侧:修改拦截条件后,检查界面上的解释是否随之变化;不变即说明两处判定不同源。
反例做不到——"保存"永远是灰的,没有任何提示,用户逐个字段试到放弃;做过头——每个禁用元素旁常驻一段解释文字,正常状态下的界面被例外说明淹没。
UI1-4选区是产品对象必须
一句话:当前选了哪些,用户动手前要能核对。
适用允许用户选中一个或多个对象并对选区下达命令的产品。
规则选区必须作为显式的产品状态维护,具有明确的建立、扩展、缩小与清除语义(见 gui.selection.model)。当前选中了哪些对象必须可见;选区可能超出当前可视范围时,必须提供计数或可核对的清单(见 gui.selection.visibility)。选区必须由用户的指定建立,禁止由滚动位置、悬停位置或未声明为选择动作的点击推定。为单个对象设计的命令不得因存在选区而自动扩大作用范围(见 gui.selection.actions.scope)。提供跨页或跨筛选的"全选"时,其实际覆盖范围必须在提交前显式呈现(见 gui.selection.include_filtered)。
边界条件本条不要求所有列表都支持多选,也不规定多选的操作方式。单选界面同样适用"当前选中什么可见"的要求,但计数与清单的要求只在多选时生效。
设计应用"选中三项"和"选中当前筛选下的全部 1,284 项"是两个语义,界面上要分得开;后者在执行前应当能展开看到范围,或至少给出准确的总数与筛选条件。
验证示例
- 用户侧:选中若干对象后滚动到看不见它们的位置,检查还能否知道选了什么、选了几个。
- 实现侧:检查命令处理接收的是选区集合还是当前高亮的单个对象;构造两者不一致的情形并观察实际作用范围。
反例做不到——勾选了一批文件,滚动之后界面上不再有任何选区信息,点删除时才知道选了 40 个;做过头——每选中一项就弹出一次确认,或把选区清单常驻占据半个屏幕。
依据与参考把选区作为可核对的一等状态,与"在提交前呈现作用范围"共同支撑 UI2-1(R04、R10、R12)。
UI1-5视图变化后选区保持或明确失效必须
一句话:排序筛选之后,选中的还是刚才那些东西。
适用选区可能跨越排序、筛选、分页、搜索或数据刷新而存续的产品。
规则视图发生变化后,选区必须按对象身份保持,或明确清空并告知用户(见 gui.selection.persistence.on_view_change)。禁止按屏幕位置保留选区,也禁止在选区所指对象已改变时不作任何提示。保持选区时,若部分对象已不在当前视图内或已被删除,其范围变化必须可被用户获知。
边界条件本条不要求选区必须跨会话保持,也不要求跨设备保持。清空选区是合法选择,本条要求的是清空这件事被告知,而不是必须保持。
设计应用把选区存成对象身份的集合,而不是行索引的集合。数据刷新时,按稳定身份核对存在性与权限;筛选外的对象按既定选择范围保留或清除,再向用户呈现"其中 3 项已不在当前筛选条件下"这类范围变化。
验证示例
- 用户侧:选中若干项后改变排序或筛选条件,检查选区所指的是否仍是原来那些对象。
- 实现侧:注入一次后台数据变更(有对象被他人删除),检查选区是否静默包含或排除了对象而无提示。
反例做不到——选中第 2、5、7 行后重新排序,选中标记还在第 2、5、7 行上,但那已经是另外三个对象;做过头——任何一次数据刷新都强制清空选区并弹窗告知,长列表上的批量操作无法完成。
UI1-6焦点、悬停与选中分别表达应当
一句话:光标在哪、鼠标在哪、选中的是哪,是三件事。
适用同时存在键盘遍历、指点悬停与对象选择的界面。
规则焦点(当前接受键盘输入的位置)、悬停(指点设备当前所指的位置)与选中(后续命令的作用对象)应当分别表达,不以同一种视觉状态混同。产品必须声明其采用的耦合模型(见 gui.selection.focus.coupling),至少区分三种:选择与焦点分离(移动焦点不改变选区,选择由确认键或点击发起);单选情形下选择随焦点移动(方向键移动焦点即改变当前选中项,这是单选列表与图库的既有惯例);多选情形按已声明的多选模型处理(移动焦点不改变选区、或按修饰键扩展选区,两者须分别说明方向键、确认键与选择变更的语义)。在选择随焦点移动的模型下,普通遍历禁止触发不可逆的业务效果——是否可以自动进行预览类加载,按其延迟成本、是否改变对象状态(如标记已读)与用户意图分别判定并记录,本条不把"发起一次预览"一概判为违例。
边界条件本条不禁止选择随焦点移动——单选列表、方向键浏览的图库、部分表格控件采用该模式是既有惯例,且在多种平台的控件语义中成立。"选择变化带动焦点"与"焦点移动带动选择"是两个方向,本条约束的是后者。本条要求的是耦合模型是明示的设计决定并附带上述限制,而不是默认状态。焦点必须可见、按任务顺序可达,并能退出当前区域;具体行为在 UI4-6 中定义。
设计应用先确定"命令作用于焦点还是作用于选区",再设计视觉。二者在同一界面内混用(工具栏命令作用于选区、快捷键作用于焦点)是常见的隐性缺陷。
验证示例
- 用户侧:用键盘遍历一个已有选区的列表,检查焦点移动是否改变了选区,以及这一行为是否与声明一致。
- 实现侧:检查焦点态与选中态是否为两个独立状态;构造"焦点在 A、选中的是 B"的情形并观察命令作用于谁。
反例做不到——键盘遍历到某项就把它标记为已读并触发了对外可见的状态变化,用户只是想往下翻;做过头——为了区分三种状态用了三组高对比色块,正常浏览时界面像调色板。
依据与参考焦点与选择在平台控件语义与无障碍模式指引中被作为不同状态处理(R08、R10、R12)。
3.2 UI2 后果可预知可撤回
这条原则管的是一次操作的后果:它会动到哪些东西、动完之后能不能退回去、退不回去的时候用什么方式让用户在动手前想清楚。它的核心主张是撤销优先于确认——确认把判断的负担放在用户按下按钮的那一瞬间,而那正是用户注意力最不可靠的时刻;撤销把判断的负担挪到后果已经可见之后。确认用于不可逆、重大影响、必要授权等确有判断价值的情形;能撤销不自动取消这些确认。
UI2-1提交前可知后果必须
一句话:动多少东西、能不能退回来,按下之前就该知道。
适用会改变系统状态、产生对外副作用或影响其他用户的操作。
规则操作的影响范围(作用于哪些对象、涉及多少数量)与可逆性(能否撤销、撤销到什么程度)必须在提交前可获知。作用于多个对象且含不可逆后果时,受影响对象的数量与具体对象都必须可获知:数量显式呈现,并同时提供可展开的对象清单或可核对的查询范围说明(见 gui.object.action.scope.display)——只给数量不满足本条。
作用范围必须明确其口径,至少区分三种并分别表达:仅当前页、当前筛选结果的全部对象、用户显式选定且跨筛选的对象集合;并须注明该范围是执行时刻的快照还是在执行时重新求值的动态查询。总数尚未核实而该数量会影响用户判断时,须先完成核对或把范围缩小到已知对象;呈现下界与不确定性只适用于不影响重要判断的情形,不是无条件放行。禁止在结果产生之后才首次告知影响范围或不可逆性。
边界条件本条不要求为每个操作都展示预览。影响范围显而易见且可逆的操作(在文本中输入一个字符、勾选一个复选框),其可见结果本身即满足本条。本条不要求逐一列举全部对象——数量准确、且可展开核对或可解析到一段明确的查询范围即可。确认之后到执行之间对象集合发生变化时(新增匹配记录、对象被删除、权限改变),执行范围不得无声扩大:按已声明的快照或动态查询口径处理,扩大范围时须重新取得用户的决定。
设计应用把"要动多少"与"能不能退"作为命令入口上的两条信息,而不是确认弹窗里的两句话。数量影响重要判断而尚未核实时,先核对或缩小到已知范围;仅在不影响重要判断时呈现下界与不确定性。
验证示例
- 用户侧:对每个不可逆操作,检查用户在按下之前能否说出会影响多少对象、能否撤回。
- 实现侧:核对界面呈现的受影响数量与实际执行的数量是否来自同一次计算。
反例做不到——点"清理缓存"之后才发现登录状态与本地草稿一并被清掉;做过头——每个操作前都插一页"影响范围预览",连改一个标题都要先看一遍摘要。
依据与参考让操作后果在执行前可评估,是缩短"执行鸿沟"与"评价鸿沟"的基本要求(R03);对不可逆的重要操作要求可撤销、可核对或可确认,在无障碍标准中有对应的成文要求(R07)。
UI2-2撤销优先于确认必须
一句话:低后果操作用撤销减轻打断,重要后果仍需相称确认。
适用提供可改变系统状态的操作的产品。
规则默认必须为可恢复的状态变更提供撤销能力;不提供时须按下述边界逐类说明。对低后果、恢复可靠且恢复成本可接受的操作,应当以撤销替代重复确认,禁止无明确收益地为其叠加确认(见 gui.reversibility.undo.mode、confirm.level)。"技术上可撤销"不单独取消确认要求:出现下列任一情形时,可以在撤销能力之外保留与后果相称的确认,并记录理由——需要取得必要授权、存在重大的累计影响、恢复不能覆盖全部后果(已通知他人、已触发外部流程)、或误操作本身即造成重要中断。撤销入口必须在操作完成后可达,且其可达性不依赖于某个会自动消失的提示(见 UI3-6)。存在对外副作用的操作,其撤销可能受时限约束时,该时限必须明示(见 gui.reversibility.undo.ttl)。不提供撤销的操作类别必须逐类记录理由,禁止以"实现成本高"作为唯一理由而不记录后果评估。
边界条件对于没有有意义恢复结果的临时导航或受不可回收后果限制的操作,可不提供撤销,但必须说明后果与可行补救;纯实现成本不构成豁免。本条不要求撤销无限深、无限久,也不要求撤销覆盖已经外发且不可回收的副作用(邮件已投递、支付已清算、通知已推送到他人设备)——那类情形按 UI2-6 处置。本条不禁止确认:不可逆操作的确认由 UI2-4 规定。安全敏感的重新验证(转账前重新输入密码)与取得必要授权的确认都不是本条所要减少的"重复确认",不受其约束。
设计应用把删除实现为"先标记、后清理",用清理窗口换来撤销能力,这是把不可逆变成可逆最常用的一种做法。同时要注意:撤销窗口的存在不构成对用户隐瞒后果的理由,UI2-1 仍然适用。
验证示例
- 用户侧:对产品中全部删除类操作,统计其中有多少提供了撤销、多少只提供了确认。
- 实现侧:检查确认弹窗的出现条件是否与
irreversible.actions清单一致;对可撤销操作上的确认逐项检查风险与授权理由,只有无明确收益的重复确认才违反本条。
反例做不到——每次删除一封邮件都弹窗确认,删完之后没有撤销;做过头——把"撤销优先"理解成所有操作都不需要任何提示,账户注销与数据导出覆盖也直接执行。
依据与参考"用户控制与自由"要求为误操作留出明确的退出口,撤销是该启发式的典型实现(R04);平台指南把撤销作为界面的常规能力而非例外能力对待(R10)。
UI2-3撤销边界对齐用户心智必须
一句话:一次撤销撤掉用户认为的那一步。
适用提供撤销能力的产品。
规则一次撤销必须对应用户可识别的一次操作,禁止把一次用户操作拆成多次撤销,也禁止把多次用户操作合并为一次撤销而不告知(见 gui.reversibility.undo.granularity)。内部事务可以有多步,但不得暴露为多次必要撤销;确属两次由用户分别发起的独立操作的,按两次操作记录,而不是作为"同一次操作"的例外。撤销的作用域必须可解析(当前视图、当前文档、当前会话,或更大的范围),并且其边界对用户可预期(见 gui.reversibility.undo.scope)。撤销栈跨视图、跨文档或跨用户共享时,该共享范围必须明示。撤销与"回退导航"是两件事,禁止用同一个入口同时承担两种语义。涉及并发编辑时,撤销必须只撤回该次操作的贡献;不能确认变更归属时,先核对并说明冲突,禁止以整份快照覆盖他人或用户后续的有效编辑。
边界条件本条不规定撤销栈的深度,也不要求撤销跨会话保持。连续的同类微操作(连续输入的字符、连续拖动的中间帧)合并为一步是符合本条的,因为用户识别的一次操作本就是"输入了这句话"而非"敲了十七次键"。
设计应用定义撤销单位时以"用户会怎么描述刚才做的事"为准,而不是以内部事务边界为准。一次拖放涉及删除与插入两次内部变更,但对用户是一步(见 UI6-4)。
验证示例
- 用户侧:执行一次复合操作后按一次撤销,检查界面是否回到操作前的状态,而不是中间态。
- 实现侧:核对撤销栈的入栈单位与用户操作的对应关系;检查跨视图操作后撤销作用于哪个视图。
反例做不到——一次"套用模板"要按二十次撤销才能退回去,中间还会停在半成品状态;做过头——把整个会话的全部操作合并成一步撤销,用户只想退回上一个改动却丢掉了一小时的工作。
依据与参考把撤销理解为"需要被支持的用户意图"而不是一条待实现的系统命令,是该领域的既有主张;一项小样本研究报告受试者更倾向于考虑操作间依赖关系的撤销模型,其样本、任务与作答方式的局限见 reference.md(R06)。
UI2-4不可逆操作按后果分级必须
一句话:确认的强度由后果决定,不由弹窗数量决定。
适用执行后不可撤销、或撤销无法覆盖全部后果的操作。
规则不可逆操作必须列入不可逆操作清单并说明后果(见 gui.reversibility.irreversible.actions);其确认强度必须与后果严重程度相称(见 gui.reversibility.confirm.level)。确认必须复述具体后果与受影响对象,禁止以"确定要继续吗"这类不含后果信息的提问充当确认,也禁止以增加确认环节的数量替代提高单次确认的信息量。后果重大且不可逆时,应当要求用户作出与该操作绑定的主动输入(键入对象名称、勾选具体后果条目),使确认无法被无意识地通过。
边界条件本条不规定各类操作对应哪一档确认,那由产品按后果评估决定并记录。本条不要求所有不可逆操作都设置主动输入;对低后果的不可逆操作施加高强度确认,是本条反例的"做过头"一侧。涉及法律、财务或数据提交的特定情形另有成文的可逆、可核对或可确认要求(见 reference.md 第三节),本条不替代该要求的符合性判定。
设计应用写确认文案时先写"完成后将发生什么、什么无法恢复",再决定这句话需要哪一档交互承载。连续两次点"确定"不会让用户想得更清楚,一次说清楚"这会永久删除 1,284 条记录,包括其中 12 条被其他人引用的"才会。
验证示例
- 用户侧:对每个不可逆操作,检查确认环节是否说出了具体后果与受影响对象数量。
- 实现侧:核对确认档位与不可逆操作清单中的后果评级是否一一对应;找出档位与后果不匹配的项。
反例做不到——"删除工作区"只弹一句"确定吗",点掉之后所有成员的数据一起消失;做过头——删除一条草稿也要求键入工作区名称,用户很快学会不读弹窗内容直接复制粘贴。
依据与参考对法律、财务与数据提交类的重要操作,成文标准要求提供可撤销、可核对或可确认三者之一(R07);错误预防优先于错误提示,是启发式评估中的既有条目(R04)。
UI2-5破坏性动作不设默认执行应当
一句话:手滑的那一下,不该正好落在最狠的选项上。
适用包含破坏性选项的确认、菜单与操作区域。
规则破坏性动作不应当成为默认焦点、默认按钮或回车键的默认目标(见 gui.reversibility.destructive.default);禁止在连续操作中无提示地将原位置的安全动作替换为破坏性动作,使连点或残留输入直接执行破坏后果。破坏性入口与常用入口应当在空间上分开,或需要与常用动作不同的动作序列。
边界条件本条不要求把破坏性动作藏起来——难以找到与容易误触是两种不同的失败。破坏性动作在其语义明确的场合作为唯一动作时(专门的"删除账户"页面上的唯一按钮),不适用位置分离的要求。
设计应用检查连续操作路径上的位置重合:上一步的"下一步"按钮与这一步的"全部删除"按钮如果落在同一坐标,用户的手会在两次点击之间保持不动。
验证示例
- 用户侧:在确认对话出现时直接按回车,检查发生的是安全动作还是破坏动作。
- 实现侧:核对全部确认对话的默认焦点位置;统计破坏性动作与上一步主要动作坐标重合的界面。
反例做不到——删除确认框的默认按钮是"删除",回车直接执行;做过头——把删除入口埋进三层菜单加一次搜索,日常清理工作变得无法完成。
UI2-6撤销失败如实说明并给出补救必须
一句话:没撤回来就别说已撤回。
适用撤销可能部分失败或无法覆盖全部后果的产品。
规则撤销未完成或仅部分完成时,系统必须如实说明哪一部分未能撤销、原因是什么,并给出可执行的补救路径(见 gui.reversibility.undo.failure.mode);禁止在撤销未实际完成时呈现"已撤销"。已经外发且不可回收的副作用(已投递的消息、已触发的第三方调用、已通知到他人设备的提醒),禁止因界面上的状态回退而被表述为已收回。撤销失败的信息内容按 UI3-5 处理。
边界条件本条不要求系统能撤销一切;它要求的是关于"撤销到什么程度"的表述与事实一致。
设计应用把撤销的结果本身当成一次阶段与结果分开的操作来处理(UI3-2),而不是当成一次必然成功的界面回滚。
验证示例
- 用户侧:在网络中断条件下执行撤销,检查界面呈现的是"已撤销"还是"未能撤销,原因与下一步"。
- 实现侧:注入下游服务拒绝回滚的响应,检查本地状态是否已经回退而对外表述仍称已撤销。
反例做不到——撤销发送后界面显示"已撤回",但对方设备上的通知还在;做过头——因为撤销可能失败,就在每次撤销前先弹一次"撤销可能不完全生效"的提示。
依据与参考本地状态回滚与对外副作用回收是两件事,这一区分在乐观更新的工程实践中同样成立(R13、R14)。
3.3 UI3 状态与反馈可见
这条原则管的是系统对一次操作作出的回应。它的核心主张是阶段与结果分开:输入已接收、正在执行、处理结束回答“到哪了”;成功、失败、部分成功、未知回答“结果有何依据”。把它们合并成一个加载动画,用户就无法区分"它没听见"与"它正在做"与"它做完了但结果没变"。本原则还管一件在现代界面里越来越普遍的事:界面先变、服务端后确认——这种做法本身没有问题,问题在于失败之后界面悄悄改回去,而用户以为事情已经办成了。
UI3-1操作被受理有即时反馈必须
一句话:先让人知道"它听见了"。
适用结果不会在操作发生的同一时刻可见的操作。
规则操作被系统受理这件事必须有可感知的反馈,且该反馈必须出现在用户当前能够发现的位置(见 gui.feedback.ack.mode、placement)。受理反馈禁止被表述为完成:它只承诺"输入已被接收",不承诺结果。反馈的延迟上限由产品按目标场景与人群测定并记录依据,本规范不给数值。
边界条件操作结果本身即时可见且不可能失败时(切换一个纯本地的展开状态),结果即为反馈,不需要额外的受理表达。本条不要求每次点击都有独立的视觉反馈元素——原位的状态变化即可。状态消息必须可被辅助技术感知,普通进度更新不得抢走输入焦点;高频进度应当合并播报,失败与需要用户处理的状态不能被合并丢失(见 gui.feedback.announcement.policy)。
设计应用把受理反馈放在用户的手所在的位置(被点击的那个元素上),而不是屏幕角落。跨区域生效的操作两处都需要:动手的地方与生效的地方。
验证示例
- 用户侧:在人为增加的网络延迟下操作,检查用户是否会因为"没反应"而重复点击。
- 实现侧:统计同一操作在短时间内的重复提交次数,重复率高提示受理反馈缺失或不可见。
反例做不到——点击提交后界面完全没有变化,用户连点五次,产生五条记录;做过头——每个点击都触发一次全屏遮罩加载动画,连切换标签页都要等一下。
依据与参考关于响应时间与用户感知的经典分档(约 0.1 秒、1 秒、10 秒的量级差异)常被用作反馈设计的参考起点(R05);状态消息的辅助技术呈现参见 R20;本规范不把这些数值转写为通用门槛,产品值须自行测定。
UI3-2阶段、结果与未知分别可辨必须
一句话:已接收不等于已完成,未收到结果也不等于失败。
适用存在异步执行、后台处理或对外调用的操作。
规则操作阶段与操作结果分别表达。阶段按能力区分本地已接收、已排队、执行中、已结束,另保留阶段未知;结果区分待定、成功、失败、部分成功、已取消、未知。尚未结算但可正常追踪为待定;无法确认事实为未知。各项语义必须可辨(见 gui.feedback.states)。禁止用同一种呈现同时表示其中两种以上的语义,也禁止以"没有报错"推定成功。它们可以共用同一处界面位置,但语义不得合并。
取不到结果依据时必须保留"未知"并提供核对路径:请求超时、响应丢失、连接中断都不构成对成败的推定——禁止把未知改写成"失败"或"尚未提交",也禁止由计时器推定完成。重试在什么条件下是安全的(是否幂等、是否已有防重保障),须另行声明;未声明时不得自动重发。
边界条件本条不要求每种状态都有独立的视觉组件;一个状态标签在各取值之间切换即满足,也不要求每个界面都展示全部维度。本条不适用于结果同步可见且不可失败的纯本地操作——此类操作按 gui.feedback.states 记"不适用"并写明依据。
设计应用先把阶段、结果与事实依据写进状态模型,再设计呈现。工程实现中最常缺的是"已受理但尚未开始"这一态——请求已发出、队列尚未处理,此时界面上通常什么都没有。
验证示例
- 用户侧:分别构造慢速成功、快速失败与长期排队三种情形,检查界面呈现是否可区分。
- 实现侧:检查状态机是否分别表达阶段与结果、结果是否含"未知"取值;核对是否存在"超时即视为成功"或"超时即视为未提交"的分支;核对未知状态下是否存在自动重发。
反例做不到——上传界面只有"转圈"和"不转圈"两种样子,失败之后转圈停下,用户以为传完了;做过头——为每种状态各设计一套独立组件,简单操作的界面被状态说明占满。
依据与参考"系统状态可见"是启发式清单中的首条,其要求是在合理时间内让用户知道正在发生什么(R04);平台指南对进行中与完成的反馈作了分别的呈现建议(R10、R11、R12);响应丢失与安全重试的机制边界见 R21。
UI3-3进行中给出可判断的信息应当
一句话:能不能取消、要不要等,比进度条本身更有用。
适用耗时可能超出用户等待预期的操作。
规则进行中的操作应当提供支持用户决策的信息:能否取消、是否阻塞其他操作、还剩多少或剩余量未知(见 gui.feedback.progress.info)。禁止以循环动画或计时器伪造完成比例,也禁止在无法取消时呈现取消入口。无法给出完成比例时,如实呈现"剩余量未知"优于给出一个不成立的估计。不定进度动画可以表达仍在等待,但不得被读作完成比例。可取消的操作必须区分取消请求已接收、取消已生效与结果待核对;已完成部分须保留回执,不得被“已取消”抹去。取消本身按 UI3-2 的阶段、结果与未知处理。
边界条件本条不要求所有耗时操作都提供精确进度。"等待预期"的门槛由产品按目标场景与人群测定并记录依据,本规范不给数值。
设计应用用户在等待期间要作的决定通常只有三个:继续等、去做别的、取消掉。进度条只服务第一个,另外两个需要"是否阻塞"和"能否取消"。
验证示例
- 用户侧:在长耗时操作进行中尝试执行其他操作,检查界面是否说明了阻塞范围。
- 实现侧:核对取消实际阻止了哪些未完成动作;取消与完成同时到达时,显示最终核实结果,不能只关闭提示。
反例做不到——大文件导出只有一个转圈,用户不知道能不能切走,只好守着;做过头——为了显示精确进度而先做一次全量扫描,等待时间因此翻倍。
UI3-4乐观更新须可回滚且回滚可见必须
一句话:先显示后确认可以,失败了偷偷改回去不行。
适用在服务端确认之前就把预期结果呈现给用户的界面(乐观更新)。
规则采用乐观更新时,系统必须能在失败后把界面与本地状态回滚到一致状态,并必须让用户知道哪一步没有成功(见 gui.feedback.optimistic.mode)。禁止静默回滚:界面上曾经出现过的结果在失败后消失,而没有任何说明,属于本条违反。乐观更新的适用范围必须声明——不可逆操作与产生对外副作用的操作,禁止采用乐观更新呈现为已完成。回滚覆盖的状态范围(界面、本地缓存、派生的计数与排序)必须一并声明。
边界条件本条不反对乐观更新——它对可逆、低失败率、结果局部可见的操作是合理做法。本条也不要求回滚必须逐字还原用户在此期间的其他输入:必须保留后续有效编辑。并发请求的失败只撤回失败操作的贡献,或重新读取可信状态并对保留的用户输入作冲突处理;禁止用旧快照覆盖后续成功操作。结果未知时保留待核对标记,不按确定失败盲目回滚(见 gui.feedback.concurrency.policy)。
设计应用把"乐观呈现的状态"与"已确认的状态"在数据层分开,让界面能表达"这条还没确认"。失败后的呈现应当保留用户的意图(重试入口、编辑内容),而不是把界面恢复成用户从未操作过的样子。
验证示例
- 用户侧:在离线或服务端拒绝的条件下执行操作,检查界面是先呈现成功随后无声还原,还是明确告知失败。
- 实现侧:检查失败分支是否覆盖了全部派生状态(列表计数、排序位置、未读数),而不只是主对象。
反例做不到——点赞立刻加一,请求失败后数字悄悄减回去,用户以为点上了;做过头——因为担心失败,所有操作都等服务端确认后才呈现,本地的排序与折叠也要等一个来回。
依据与参考主流数据层库把"失败后回滚到先前状态"作为乐观更新的组成部分,而非可选补充(R13、R14);这些文档描述机制存在与用法,不证明某个产品该不该采用乐观更新。
UI3-5失败可定位到对象与原因必须
一句话:二十个里坏了三个,就得说是哪三个。
适用可能失败的操作,尤其是作用于多个对象的批量操作。
规则失败信息必须包含受影响的对象、失败原因与可执行的下一步(见 gui.feedback.failure.content)。作用于多个对象时,必须逐对象报告结果,禁止以整体结论掩盖部分失败(见 gui.feedback.batch.result.granularity)。部分成功的情形必须明确呈现为部分成功,并说明已生效的部分是什么、是否可回退。重试是否安全(会不会产生重复副作用)必须可获知;重试必须保留同一次操作的身份,只处理经核实未成功的对象,禁止重复执行已成功项(见 gui.feedback.retry.policy)。
边界条件本条不要求向用户暴露内部错误码或堆栈。原因的粒度以"用户能据此判断下一步"为准;确因安全考虑不能披露具体原因时,须说明这一点并给出求助路径,而不是给出一个不成立的原因。
设计应用批量操作的结果呈现按"成功多少、失败多少、失败的是哪些、失败原因分几类"组织,并让失败项可以被重新选中后重试。
验证示例
- 用户侧:构造 20 项中 3 项失败的批量操作,检查用户能否找出是哪 3 项、为什么失败。
- 实现侧:核对批量接口的返回是否保留了逐项结果;检查界面是否把逐项结果折叠成了单一结论。
反例做不到——批量导入完成后只显示"部分记录导入失败",没有任何定位手段;做过头——为每一项失败都单独弹一个对话框,20 项失败弹 20 次。
依据与参考帮助用户识别、诊断并从错误中恢复,是启发式清单中的独立条目,其要求包括用可理解的语言指出问题并给出建设性的下一步(R04)。
UI3-6反馈的存续时间不构成操作期限应当
一句话:撤销入口不该跟着提示一起消失。
适用使用自动消失的提示承载操作反馈的产品。
规则自动消失的提示,其存续时间不应当成为用户完成后续动作的期限;撤销、重试、查看详情等入口禁止仅存在于会自动消失的提示中(见 gui.feedback.notice.duration)。提示的存续时长由产品按目标人群的阅读与操作时间测定并记录依据,本规范不给数值。承载失败信息的反馈不应当自动消失,除非同一信息在别处持续可达。
边界条件本条不禁止自动消失的提示——它对成功且低后果的操作是合适的。本条也不要求撤销入口常驻界面:把它同时放进一处持久的位置(操作历史、编辑菜单、对象自身的状态)即满足。
设计应用把提示当成"通知这件事发生了"的通道,把撤销当成"这件事可以回退"的能力,两者分开实现。能力不随通知消失,是这条规则的全部内容。
验证示例
- 用户侧:执行一次可撤销操作后等待提示消失,检查是否仍能撤销。
- 实现侧:核对撤销能力的生命周期是否绑定在提示组件上。
反例做不到——删除后的"已删除,撤销"提示 4 秒后消失,用户回过神来已经没有入口;做过头——每个操作都留下一条不会消失的提示,屏幕上堆了十几条历史通知。
3.4 UI4 输入方式对等
这条原则管的是产品声明支持哪些输入方式,以及这些声明是否兑现。它的核心主张是:对等的判据是任务能不能完成,不是手势能不能复现。触屏上没有悬停,键盘上没有坐标,手柄上没有精确指点——要求它们互相模仿动作,是把对等做反了。本原则同时规定键盘与辅助技术的可达性、焦点流转、靶区及指针取消,避免“支持某种输入”只停留在能力声明。
UI4-1核心任务在每种声明支持的输入方式下可完成必须
一句话:对等的是任务,不是手势。
适用声明支持多种输入方式的产品。
规则产品必须声明输入方式与核心任务清单(见 gui.input.methods、core_tasks)。每种输入方式分别记录完整支持或限定范围支持:完整支持必须能完成全部核心任务;限定范围支持必须列出可完成的任务子集、缺口与替代路径,不得宣称全部对等。禁止用模拟鼠标坐标或某一手势替代任务完成验证。
核心任务至少覆盖产品主要成果,以及完成该成果所需的创建、选择、修改、提交、恢复和退出;不提供某项能力时记录依据,禁止为掩盖通道缺口删掉任务。键盘可操作、单指针拖动替代等明确适用的要求仍按实际功能覆盖,不能以支持档位或核心任务清单缩小其范围。
边界条件本条不要求支持所有输入方式;声明支持的范围由产品决定。本条也不要求各输入方式的效率相同——路径长短可以不同,但任务必须可完成。专为特定输入设计的产品(数位板绘画工具的笔压功能、体感游戏的动作输入)可将该能力排除在核心任务清单之外并说明理由。
设计应用先写核心任务清单,再逐个输入方式走一遍完整路径。这份清单是本条的任务验证依据——没有它,"支持键盘"只是一句无法被证伪的话。
验证示例
- 用户侧:拔掉鼠标、只用触屏、只用键盘各走一遍核心任务清单,记录哪些任务无法完成。
- 实现侧:核对核心任务清单是否存在且可解析到具体任务,而不是写成"主要功能"。
反例做不到——只有把滑块拖到位才能设置数值,键盘用户无法输入;做过头——为每种输入方式各做一套独立界面,同一个功能维护四份,行为逐渐不一致。
依据与参考输入方式无关的操作路径要求在无障碍标准与多平台指南中均有对应条目(R07、R08、R12)。
UI4-2悬停与上下文菜单不作为唯一入口必须
一句话:触屏上没有悬停,那些功能不能就此消失。
适用使用悬停显示、右键菜单或长按菜单承载功能入口的界面。
规则完成核心任务所必需的信息与操作,禁止仅在悬停状态或上下文菜单中存在(见 gui.input.hover.role、context_menu.role)。悬停与上下文菜单可以作为快捷通道,但必须存在可发现、无需悬停或右键即可进入的等价入口;常驻的“更多操作”按钮即可,不要求全部命令平铺。悬停承载的补充信息(说明、预览、完整文本)在无悬停能力的输入方式下必须有可达的等价呈现。
边界条件本条不禁止悬停效果,也不禁止右键菜单——它们在指点设备上是高效的。本条约束的是"唯一性":作为加速器合规,作为唯一路径不合规。纯装饰性的悬停反馈不在本条约束范围内。作者提供的悬停或聚焦补充内容应当可关闭、可将指针移入阅读,并在用户仍需阅读时保持;仅在不遮挡或替换内容、错误提示等适用例外下省去关闭机制。
设计应用把上下文菜单的内容视为常驻入口的一份副本,而不是它的替代。设计评审时的检查方式很简单:把悬停与右键都关掉,看核心任务还能不能走完。
验证示例
- 用户侧:在触屏设备上完整走一遍核心任务,记录哪些功能找不到入口。
- 实现侧:列出所有仅由悬停或右键触发的命令,逐个核对是否存在常驻等价入口。
反例做不到——重命名只能通过右键菜单,触屏长按又被系统手势占用,该功能在移动端事实上不可用;做过头——把所有右键菜单项都平铺到工具栏上,工具栏挤满几十个图标。
UI4-3切换输入方式不重置工作状态必须
一句话:放下鼠标拿起键盘,选区和草稿还在。
适用同一设备上多种输入方式可能交替使用的产品。
规则用户在同一会话中切换输入方式时,选区、草稿、滚动位置、展开与折叠状态以及进行中的操作必须保持(见 gui.input.switch.preserved);禁止因输入方式变化而重置这些状态。因输入方式变化引起界面形态变化时(触摸模式下的密度调整),状态保持的要求同样成立。布局变化时按同一内容锚点保持阅读位置,不要求机械保持滚动像素。
边界条件本条不要求光标位置或悬停焦点跨输入方式保持——那些是与设备绑定的瞬时状态。本条也不禁止在输入方式变化时调整呈现密度或控件尺寸。"已告知状态被重置"不构成本条的满足:告知是必要的,但它不解除保持义务;确实无法保持时,该产品不得声明支持多种输入方式的并存(见 UI4-1、UI4-5)。
设计应用把工作状态(选区、草稿、位置)与设备状态(指针位置、悬停对象)在数据层分开。二者混在一处时,输入方式的切换会连带清掉工作状态。
验证示例
- 用户侧:在二合一设备上从触屏切到键盘鼠标,检查已选中的对象与未提交的输入是否还在。
- 实现侧:检查输入方式变化的处理逻辑是否触发了视图重建;核对重建是否保留了选区与草稿。
反例做不到——在平板上选中十几个文件后接上键盘,界面切换为桌面模式,选区清空;做过头——为了保持状态而在输入方式变化时完全不调整控件尺寸,触摸时热区过小。
UI4-4靶区与精度要求可测量必须
一句话:测的是能点中的范围,不只是图标有多大。
适用提供指点输入(鼠标、触摸、笔、遥控指针)的产品。
规则可操作元素的靶区尺寸下限、间距要求及其例外,必须引用既有的无障碍标准与设计系统规定并可解析到来源(见 gui.input.target_size.ref);尺寸必须按实际命中区域测量,并记录单位、输入方式、来源与例外;禁止把图标边界直接当作靶区证据。不同输入方式的精度差异必须体现在靶区决策中,而不是要求用户提高操作精度。
边界条件Web 指针目标采用 WCAG 的 2.5.8(AA)时,以 24×24 CSS px 或其明确的间距、等价控件、行内、用户代理控制、必需例外判定;这不是所有平台的舒适尺寸推荐。CSS px、pt、dp 不互换。产品可根据输入精度提高尺寸,不能用自行设定的较小值替代适用下限。既有标准中的例外条款(行内元素、等价控件、用户代理默认样式、功能必需)不得在引用时被删去。
设计应用把靶区规定写成一处可引用的来源,并在其中标注所依据的标准条款与例外条件,而不是在每个组件里各写一个数字。
验证示例
- 实现侧:测量实际靶区,覆盖边缘点击、相邻热区与缩放;使用间距例外时检查以小靶区为中心的 24 CSS px 直径圆不与其他目标或其他小靶区的对应圆相交。
反例做不到——移动端图标按钮只有十几个像素见方,无任何尺寸依据;做过头——把所有元素一律放大到统一下限,忽略标准中允许的等价控件与行内例外,信息密度大幅下降。
依据与参考靶区尺寸的最小值及其例外在现行无障碍标准中有成文条款(R07);平台设计指南另有各自的推荐值与适用条件(R10、R11、R12)。本规范只引用,不裁剪其例外。
UI4-5输入能力差异明示而非静默降级应当
一句话:做不到就说做不到,并给一条别的路。
适用某些功能在部分输入方式下确实无法对等实现的产品。
规则功能在某种输入方式下受限时,该限制应当明示,并给出可执行的替代路径(见 gui.input.capability.gaps);禁止在功能不可用时不作说明,仅让入口消失或点击无反应。能力差异清单应当逐项记录受限的输入方式、受限的功能、替代路径与该限制的理由。
边界条件本条不要求消除所有差异——有些差异来自设备本身(没有压感的设备无法实现压感输入)。本条要求的是差异被说出来,且不以静默消失的方式呈现。
设计应用在能力说明与帮助内容中维护这份差异清单,并让它与实际实现同源,避免文档与产品各说各话。
验证示例
- 用户侧:在受限的输入方式下访问该功能,检查是否得到了说明与替代路径。
- 实现侧:核对差异清单是否为空;空清单须有实际核对记录支持,而不是未曾检查。
反例做不到——手写批注功能在无笔设备上入口直接不显示,用户以为产品没有这个功能;做过头——在每个页面顶部常驻一条"部分功能在当前输入方式下受限"的横幅。
UI4-6图形层不阻断键盘与辅助技术路径必须
一句话:自定义控件和拖放实现,不能把路堵死。
适用提供可操作控件、弹层或动态内容的图形界面。
规则除输入路径本身不可替代的功能外,界面功能必须可由键盘操作。控件必须暴露可访问名称、角色、值与状态;可见标签应包含在可访问名称中。图形层不得破坏平台既有访问路径。键盘焦点必须可见、顺序符合任务逻辑、不被作者创建的内容完全遮挡;用户必须能进入与离开操作区域(见 gui.input.keyboard.policy、focus.policy)。
模态对话打开后,焦点必须进入其中的合适位置,Tab 遍历留在对话内部,背景不能继续操作;提供可达的取消或关闭入口。关闭后回到触发者;触发者已不存在时,移到符合下一步任务的位置。非模态浮层不得无故困住焦点。删除行、虚拟列表回收节点或刷新内容后,焦点必须落在可解释的后续位置,禁止无声掉回页面起点。
自定义控件可以接管实现该模式所需的按键,但必须保留进入、退出与文本编辑路径。单字符快捷键必须可关闭、改为组合键或仅在对应控件聚焦时生效;全局快捷键不得截获文本输入、输入法选词与平台保留命令。
边界条件本条不要求本规范范围内完成无障碍符合性评估,也不替代该评估。本条不禁止使用画布或自绘——它要求的是这类实现附带等价的访问路径。
设计应用把"这个自定义控件对应哪个已有的交互模式"作为设计交付的一部分。既有的交互模式指引对常见模式(网格、树、列表框、对话框)给出了成体系的键盘交互约定,可作为设计参照(见 reference.md 第三节)。
验证示例
- 用户侧:仅用键盘遍历含自定义控件的界面,检查是否存在无法进入或无法离开的区域。
- 实现侧:检查键盘与读屏的完整任务路径、模态开关的焦点去向、虚拟列表中焦点对象的稳定性;不能仅以是否调用事件拦截方法判断合格。
反例做不到——自绘的表格控件在键盘遍历时整块跳过,内部单元格无法到达;做过头——为迎合工具检测而给每个装饰元素都加上角色标注,辅助技术读出大量无意义信息。
依据与参考常见交互模式的键盘约定与角色语义在公开的交互模式指引中有成体系的描述(R08,该文档为非规范性指引,不作为符合性判定依据);焦点遮挡的最低要求见 R20。
UI4-7指针动作可在提交前取消必须
一句话:按错时能移开,松手不应把错误坐实。
适用产品解释的点击、触摸、笔输入及长按动作。
规则必须声明按下、移动、释放与取消事件的语义(见 gui.input.pointer.policy)。普通按钮应当采用平台激活事件,在有效目标上释放时执行;按下后移出目标再释放不得执行。采用按下即生效的交互时,必须提供相应的释放反转、完成前取消或完成后撤销机制,或记录按下时刻本身不可替代的理由。禁止将误触防护仅做成视觉按压态而业务已经提交。
边界条件演奏键盘等依赖按下时机的功能可以采用即时触发。持续按压与拖放各有完成边界,不能用按钮的移出逻辑一概取代;具体行为须与用户可见反馈相符。平台自行提供且产品未修改的输入行为按平台契约验证。
设计应用优先使用原生按钮的激活机制。拖动阈值内仍是候选点击,跨过阈值进入拖动后不得再补发一次点击;滚动手势不能顺便触发卡片动作。
验证示例
- 用户侧:按住删除按钮后移开再松手、长按后取消、按下后开始滚动,均不会意外提交。
- 实现侧:注入指针取消、焦点丢失与拖动后的点击事件,核对同一次动作不会重复激活。
反例做不到——手指刚触到删除按钮就删除,移开也来不及;做过头——每次点击都要求长按或二次确认。
依据与参考W3C 指针取消条款及说明给出了释放、反转与必需情形的边界(R17)。
3.5 UI5 录入是一类承诺
用户在界面里打字、勾选、上传、拖入的那些还没提交的东西,是一类特殊的对象:它们承载用户已经投入的工作,却还没有完成业务提交。这条原则管的就是这段"已经付出、尚未落地"的时间——东西会不会丢、什么时候告诉他写错了、告诉了之后他知不知道怎么改、提交失败之后要不要重打一遍、以及"已保存"这三个字到底承诺了什么。这个领域的失败大多不惊人,只是让人重来一遍;但重来一遍是这类产品最常见的用户流失点。
UI5-1未提交的内容不因系统行为丢失必须
一句话:人写下的东西,不该被刷新一下带走。
适用允许用户输入多字段内容、长文本或上传内容的产品。
规则用户已输入但尚未提交的内容,禁止因系统一侧的行为而丢失——包括自动刷新、会话过期、令牌续期、布局切换、后台更新、导航跳转与非用户发起的重载。系统必须声明草稿的保存策略与保留期限(见 gui.entry.draft.mode、draft.ttl);不保存草稿是合法选择,但必须在用户开始投入之前说明,不得在丢失发生之后才告知。"不保存草稿"限制的是崩溃、关闭与跨会话之后的恢复承诺,不豁免本条对系统一侧行为的禁止——同一会话内由自动刷新、会话过期、令牌续期、布局切换或非用户发起的重载造成的丢失,在任何草稿策略下都不允许。
边界条件本条不要求保存用户明确放弃的内容,也不要求跨设备保存。设备断电、进程被系统终止等超出产品控制的情形,本条要求的是尽力保存与恢复时的如实说明,不要求绝对保证。出于安全或合规不得留存的字段(支付凭据、一次性验证码)可排除在保存范围外,须逐项列出理由。
设计应用把"保存草稿"与"提交"实现为两条独立路径,前者不经过业务校验。会话过期时先保住内容再要求重新登录,登录后回到原处继续,而不是登录后回到空表单。
验证示例
- 用户侧:填到一半让会话过期,重新登录后检查内容是否还在。
- 实现侧:在输入过程中触发一次后台强制刷新与一次布局断点切换,检查已输入内容是否保留。
反例做不到——填了二十分钟的表单,令牌过期后跳转登录页,回来是空白;做过头——把用户明确点了"放弃"的内容也恢复出来,或把包含敏感信息的草稿长期同步到服务端。
UI5-2校验时机与错误位置对齐输入过程必须
一句话:别在人还没写完的时候说他写错了。
适用对用户输入进行校验的产品。
规则校验时机必须与输入过程对齐(见 gui.entry.validation.timing):禁止在用户尚未完成该字段的输入时判定其为错误,除非该输入已可判定为错且不会随后续输入变对。错误必须可定位到具体字段(见 gui.entry.error.placement);存在多个错误时,必须能从汇总处到达具体字段,且该定位不依赖用户自行查找。字段级错误与提交级错误须可区分。
边界条件本条不禁止即时反馈——正向的即时提示(密码强度、剩余字数、格式已符合)不受本条限制,因为它们不宣布错误。完成输入以离开字段或明确完成为主要依据;停顿只能用作补充信号,不能把输入法组合过程或短暂停顿直接判作完成。已显示的错误应当在修正成立后及时清除;异步校验必须绑定被校验的内容,过时响应不得重新标记已修改的字段。
设计应用把"这个值现在不合法"与"这个值不可能变得合法"分开。邮箱输入到第三个字符时前者成立而后者不成立,此时不该报错;输入了不允许的字符时后者成立,此时可以即时提示。
验证示例
- 用户侧:逐字符输入一个最终合法的值,记录中途出现红色错误的次数。
- 实现侧:核对每条校验规则绑定的触发时机;找出绑定在每次按键上的规则。
反例做不到——邮箱输入框在敲下第一个字母时就标红"邮箱格式不正确",直到最后一个字符才变绿;做过头——全部校验都推迟到提交时,用户填完十五个字段后一次收到八条错误。
依据与参考校验时机与错误可定位性对表单完成率的影响在可用性研究与行业调研中有持续讨论(R15);这些研究说明问题存在,不直接证明某一种触发时机适用于所有表单。
UI5-3错误信息说明如何改对必须
一句话:"格式不正确"没有告诉任何人该怎么办。
适用会向用户报告输入错误的产品。
规则错误信息必须说明哪里错、判错的依据是什么、怎么改成对的(见 gui.entry.error.content);禁止只宣布错误而不给出可执行的修正方向。对语义不变且规则可靠的格式规范化,应当自动处理并让用户可以看到与撤回该修正;姓名、地址、代码、密码等可能改变含义的内容必须保留原值或让用户选择建议,不得以格式整理为由静默改写,而不是要求用户手动改成系统接受的样子。错误信息使用用户能理解的语言,禁止直接呈现内部错误码作为唯一信息。
边界条件本条不要求披露完整的校验规则——出于安全考虑不宜说明的(登录失败的具体原因),可给出概括说明与求助路径,须说明这属于有意的限制。
设计应用写错误信息时按"是什么—为什么—怎么办"三段检查,缺任一段都要补。规则中的门槛(长度、字符集、取值范围)应当在出错前就可见,而不是靠试错发现。
验证示例
- 用户侧:对每条错误信息,检查一个不了解内部规则的用户能否据此一次改对。
- 实现侧:统计错误文案中不含修正方向的比例。
反例做不到——"输入无效";做过头——把完整的正则表达式与内部校验规则原文贴给用户。
依据与参考错误信息应当用可理解的语言指出问题并给出建设性方案,是启发式清单中的成文条目(R04)。
UI5-4提交失败保留已输入内容必须
一句话:系统的失败不该由用户重打一遍来赔。
适用存在可能失败的提交动作的产品。
规则提交失败时,用户已输入的内容必须完整保留(见 gui.entry.submit.failure.retain);禁止清空表单要求重填。因安全或合规不得回填的字段须逐项列出并说明理由,其余字段一律保留。提交失败后必须能在保留内容的基础上修正或安全重试;结果未知时先核对,永久拒绝时给出修正或求助路径,重试是否会产生重复副作用须可获知(见 UI3-2、UI3-5)。上传或附件类内容在提交失败后同样适用本条,不得要求重新上传已成功传输的部分。
边界条件本条不要求保留超出产品控制范围的内容(浏览器崩溃后的内存内容),那部分由 UI5-1 的草稿策略承担。
设计应用把提交失败的界面设计成"在原处继续"而不是"回到起点":错误定位到具体字段,光标可以直接落到需要修改的位置。
验证示例
- 用户侧:填写完整表单后在提交时注入服务端错误,检查内容是否还在、错误是否定位到字段。
- 实现侧:核对提交失败分支是否触发了表单重置;检查已上传附件在失败后的存续。
反例做不到——注册表单提交失败,密码、验证码与全部资料一起清空;做过头——把一次性验证码与支付凭据也回填保留。
UI5-5离开确认以实质变更为条件应当
一句话:没改过东西就别拦,拦了就要说清丢什么。
适用会在用户离开时拦截并询问的产品。
规则离开确认应当以存在实质未保存变更为触发条件(见 gui.entry.leave.guard);禁止在没有变更或变更已保存时拦截。应用自身可控制的导航(应用内路由、标签页切换、关闭对话框)触发拦截时,应当提供保存、放弃、取消三个可分别执行的选项,并让"放弃"会丢失什么可见。由运行环境控制的离开(关闭浏览器标签页、系统级返回)只能使用该环境实际提供的提示能力——其文案与按钮通常不可定制、且可能要求先有用户交互;此时本条要求的是不滥用该能力,并另行保证草稿策略本身能承接内容,不得为满足"三个选项"而声称实现了环境不支持的效果。禁止把离开确认当作草稿保存的替代——已按 UI5-1 保存草稿的情形,通常不需要拦截。
边界条件本条不规定拦截的实现方式;不同运行环境对离开拦截的控制程度不同,部分环境限制自定义提示内容并要求先有用户交互(见 reference.md 第三节)。离开提示不是持久化机制:它至多提醒一次,不替代 UI5-1 的草稿保存。
设计应用"实质变更"的判定要排除仅由系统写入的默认值、格式化结果与焦点移动产生的空变更。判定过宽会让拦截在用户什么都没做时出现,几次之后用户就学会了闭眼确认。
验证示例
- 用户侧:打开表单后不作任何修改直接离开,检查是否被拦截。
- 实现侧:核对变更判定是否比较了实质内容,还是仅记录了"表单被触碰过"。
反例做不到——打开页面看了一眼就走,弹出"您有未保存的更改";做过头——把拦截做成无法绕过的模态流程,用户在只想关掉标签页时被迫先处理表单。
依据与参考运行环境对离开拦截的限制(自定义提示受限、需要先有用户交互)在相关规范与平台文档中有成文说明(R09)。
UI5-6自动保存与业务提交语义分开必须
一句话:"已保存"到底指哪一层,要说得出来。
适用呈现保存、同步或提交状态的产品。
规则每一处“已保存”“已同步”“已完成”必须映射到可核验的事实条件(见 gui.entry.save.semantics):存储位置、本机持久化是否确认、远端持久化是否确认、业务提交结果、对外效果依据。远端草稿可以存在而本机没有持久副本;本机草稿也可以存在而从未业务提交。禁止将这些独立事实压成互斥的三级状态,禁止用自动保存表示业务已提交,或用提交已受理表示对外效果已完成。
边界条件只展示当前用户需要判断的事实,不要求把全部维度放到界面上。无法取得存储回执时标记保存待确认或结果待核对,不从动画结束、请求发出或本机编辑完成推断成功。
设计应用“已保存在此设备”“草稿已保存到服务器,尚未提交”“提交结果待核对”分别绑定不同事实。保存对象必须绑定相应内容;上一段文本保存成功的迟到回执,不得把仍未保存的新输入标成已保存。
验证示例
- 用户侧:分别测试本机离线草稿、仅远端草稿、业务已提交但通知未发出,用户能区分保存与生效。
- 实现侧:检查每处文案的事实映射;让保存 A 的回执晚于编辑 B 到达,B 仍须显示未保存或保存中。
反例做不到——离线编辑时界面显示"已保存",用户换台设备打开发现改动全无;做过头——每次输入停顿都在界面上显示一遍三层状态的完整说明。
UI5-7输入辅助与组合输入不中断必须
一句话:让人用自己的输入方式写完,不把选词当提交。
适用接受文本、凭据或重复资料输入的界面。
规则输入法组合中的候选内容不得被校验、自动格式化或重新渲染破坏;确认候选词所用的 Enter 不得同时提交表单,取消候选所用的 Esc 不得同时关闭编辑器。组合结束后再处理最终文本(见 gui.entry.input.policy)。粘贴、自动填充、密码管理器和平台文本编辑必须可用;确有必要限制时逐字段记录原因并提供可完成任务的替代,不得把禁止粘贴作为通用安全措施。
同一流程已提供的信息应当自动带入或可供选择,禁止无理由要求重复录入;重新输入确为任务实质、安全必需或原信息已失效时记录例外(见 gui.entry.reuse.policy)。标签、格式与输入目的必须可被感知,不能仅以输入后消失的占位文字承担标签;日期、数值、姓名等不得无说明地强制转成改变含义的格式。
边界条件密码可在当前认证过程中使用密码管理器或粘贴,同时不进入普通草稿持久化。辅助输入支持与保存敏感内容是不同决定。
设计应用中文、日文组合输入、粘贴、自动填充和语音文本输入分别测试;不要把全部输入处理只绑定在键盘按键事件上。
验证示例
- 用户侧:用输入法选词按回车,文本正常落下但没有发送;粘贴验证码或使用密码管理器可完成认证。
- 实现侧:检查组合状态、最终文本输入与快捷键处理的顺序;自动填充后模型值、校验值与屏幕值一致。
反例做不到——拼音选词回车把半句话发出,或粘贴后表单内部仍为空;做过头——为保护输入而完全禁用即时建议,或将密码长期保存为普通草稿。
依据与参考组合事件说明见 R18;重复输入与可访问认证的适用要求见 R19。本条对误提交的禁止由输入完整性承诺推导。
3.6 UI6 直接操纵有等价路径
拖放、缩放、框选、手写这些连续动作是直接操作最直观的形态:手上的动作与屏幕上的变化连在一起,中间不隔一层命令。这条原则管的是这类动作的语义与替代。它的核心主张是:连续操纵是一种输入方式,不是一项功能。把顺序调整这件事只做成拖放,那么对于用不了拖放的人来说,这个产品就没有"调整顺序"这个功能。本原则同时管操纵过程本身的可预期性——放下之前知道会发生什么,明确取消或在非法目标上松手不会留下本次操作的残余。
UI6-1拖放有非拖放的等价路径必须
一句话:拖不动的人,也得能把这件事做完。
适用使用拖放完成移动、排序、归类、上传或参数调整的产品。
规则拖放禁止作为任何功能的唯一通道(见 gui.manipulation.drag.mode)。每一项通过拖放完成的功能,必须存在不依赖拖动动作的等价路径(见 gui.manipulation.drag.alternative);等价的判据是能完成同一任务,不是复现同一动作。等价路径必须可发现,不得仅存在于帮助文档或快捷键说明中。
单指针路径与键盘路径须分别成立、分别验证。由产品自身实现的拖动功能,除键盘路径外,还必须存在不要求拖动、不依赖路径型手势的单指针路径(点选源、再点选目标,或菜单命令);仅提供键盘命令不满足这一项——只能用指点设备点按、无法完成拖动动作的用户仍然走不通。多条输入路径共享同一对象、同一权限判定、同一提交时点与同一撤销边界;不同的只是输入手段,不因此产生额外一次业务动作。拖动动作本身即为任务实质内容(自由手绘、签名)、或该行为由运行环境提供而产品未作修改的,按其对应例外逐功能记录理由,并按实际适用的条款记录其适用范围与本质必要例外的成立依据,不得通过把功能移出核心任务清单来制造例外。
边界条件本条不禁止拖放,也不要求等价路径同样高效——拖放作为加速器是合理的。等价路径可以是菜单命令、剪切与粘贴、目标选择对话、键盘命令或数值输入,由产品选择,但单指针路径与键盘路径各自的成立不得由对方代证。当拖动动作本身就是任务的实质内容且不可替代时(自由手绘、签名),该功能按本条的例外逐项记录理由;把它移出核心任务清单不能代替该论证(清单的作用见 UI4-1)。
设计应用设计排序、归类或上传时,先设计非拖放路径,再把拖放作为加速器加上去。反过来做,等价路径往往会变成事后补的一个不显眼的菜单项。
验证示例
- 用户侧:分别只用键盘和只用单指针点按走完全部适用拖动功能,记录哪些任务无法完成。
- 实现侧:列出全部由拖放触发的功能,逐个核对等价路径是否存在且可发现。
反例做不到——看板只能靠拖动卡片改变状态,无法用键盘或菜单移动;做过头——把等价路径做成一个必须逐层选择的多步对话,日常使用中没有人愿意走。
依据与参考不依赖拖动动作的等价路径在现行无障碍标准中有成文条款并附例外(R07);平台指南亦要求为拖放提供替代方式(R10);拖放需通过可访问控件、对象状态与结果消息表达,不能仅靠拖动视觉效果(R08)。
UI6-2投放目标与结果在松手前可见必须
一句话:放下之前就知道会放成什么样。
适用提供拖放或其他需要指定投放目标的操纵的产品。
规则操纵进行中,哪些是合法投放目标、哪些不是、以及放下之后会变成什么样,必须在松手之前可见(见 gui.manipulation.drop.preview)。预览必须至少包含一项能表达结果的表达(结果位置、结果语义文案),而不只是"这里可以放"。禁止在松手之后才首次呈现投放结果的性质(放进了哪个容器、插入到哪个位置、替换了什么)。
边界条件本条不要求逐像素预览最终渲染结果;表达出位置与语义即可。目标数量极多时(大型画布),可只标示当前指针附近的目标,不要求全部标示。
设计应用把"能放"与"放了会怎样"设计成两层反馈:前者是目标的高亮,后者是插入位置线、占位预览或一句结果说明。只做前者是本条最常见的缺失。
验证示例
- 用户侧:把对象拖到容器边界、列表项之间与非法区域三处停住,检查界面分别表达了什么。
- 实现侧:核对是否存在合法目标与非法目标两种独立表达;检查结果预览是否与实际执行结果一致。
反例做不到——拖动文件到文件夹上只有一个通用高亮,松手后才发现是替换而不是放入;做过头——每移动几个像素就重排整个列表做实时预览,界面持续抖动,反而看不清目标。
依据与参考投放目标与结果预览是平台拖放指南中的常规建议(R10、R11、R12)。
UI6-3跨容器是移动还是复制须明示必须
一句话:拖过去之后原处还剩不剩,不能靠猜。
适用允许把对象拖到另一个容器、列表、项目或应用的产品。
规则跨容器操纵的语义(移动、复制,或由用户在操纵过程中选择)必须明示,且所取语义必须在松手之前可见(见 gui.manipulation.cross_container.semantics)。允许用户在操纵过程中切换语义时,当前所处的档位与切换方式必须可见;未作选择时的默认档必须声明。禁止让同一个动作在不同容器之间产生不同语义而不作任何区分表达。
边界条件本条不规定应当默认移动还是默认复制——不同产品的惯例不同,且同一操作在同源与跨源之间采用不同默认是既有做法。本条要求的是这个默认被声明,且当前生效的那一档在松手前可见。
设计应用跨应用或跨账号的拖放尤其需要明示——用户对"从这里拖到那里"的默认预期在不同系统间并不一致,而这类操作往往不可撤销。
验证示例
- 用户侧:在同一列表内、跨列表、跨项目三种情形下各拖一次,检查语义是否被表达且与实际结果一致。
- 实现侧:核对各投放目标对应的语义配置;找出未声明默认档的目标。
反例做不到——把任务卡拖到另一个项目,原项目里的卡片消失,用户以为是复制;做过头——每次拖放都先弹一个"移动还是复制"的选择框,最常见的同列表内排序也要选一次。
UI6-4一次操纵作为一步被撤销必须
一句话:拖错了按一次撤销就回来,不是按五次。
适用同时提供直接操纵与撤销能力的产品。
规则一次完整的操纵(一次拖放、一次缩放、一次框选后的批量移动)必须作为一步被撤销(见 gui.manipulation.undo.unit);禁止把一次操纵拆成多次撤销,也禁止让撤销停在操纵的中间状态。操纵产生的派生变更(顺序重排、归属变化、计数更新)必须与主变更一并撤销。撤销粒度的一般要求见 UI2-3。
边界条件本条不要求把连续的多次独立操纵合并为一步。用户连续拖了三个对象是三步,不是一步。
设计应用把操纵的开始与结束作为撤销事务的边界,中间的连续变化不入栈。这一点在实现层通常需要显式处理,因为操纵过程会产生大量中间事件。
验证示例
- 用户侧:完成一次跨容器拖放后按一次撤销,检查对象是否回到原容器的原位置。
- 实现侧:核对撤销栈中一次操纵对应几条记录。
反例做不到——拖动一个卡片跨列后,撤销先把它放回列首,再按一次才回到原列;做过头——把一整轮整理操作合并成一步,用户想退回上一个动作却退回了半小时前。
UI6-5中途放弃不留部分结果必须
一句话:取消当前操纵,不留下这次动作的半成品。
适用提供连续操纵的产品。
规则以预览后提交为语义的操纵在完成前被放弃时,必须清除本次预览并恢复其改动前状态,同时保留无关的并发变更,禁止留下部分结果(见 gui.manipulation.abort.methods)。放弃的方式至少包含一种可发现的显式方式(取消键、放回原处、在非法目标上松手、移出可投放区域);任一放弃方式都不得把本次预览留成业务结果。预览中的临时状态禁止被当作已提交业务结果。系统夺取指针、触点丢失、窗口失焦等中断必须有明确处置,不能遗留“正在拖动”。
边界条件音量等持续生效控件应明确区分“结束调整并保留当前值”与“取消并恢复原值”,按 gui.manipulation.commit.policy 声明生效和补偿边界;不得把已生效的动作标成无后果预览。目标被他人删除时不得为恢复起点而复活该对象。无法核实远端结果时转为待核对,不声称已还原。本条不要求操纵过程中的界面变化(占位、预览、临时高亮)在放弃后逐帧还原,它要求清除本次操纵未提交的变化并保留有效的外部变化。因外部原因中断(对象在操纵过程中被他人删除、连接断开)时,本条要求明确告知已知影响与待核对部分,而不是隐藏不确定性。
设计应用对移动、排序等采用临时预览层和明确提交边界;对持续生效控件保留起始值并定义补偿,无法补偿的影响提前说明。两种做法分别验证,不能用“每帧都写数据”来假装已具有取消机制。
验证示例
- 用户侧:拖起对象后按取消键、拖到非法区域松手、拖出窗口松手,检查三种情形是否都无变化。
- 实现侧:按提交策略检查预览是否提前写入、持续生效是否可结束或补偿;注入中断并核对残留与并发编辑。
反例做不到——拖动到一半按 Esc,对象已经从原列表移除但没有进入任何目标,界面上消失了;做过头——为了保证可放弃而在每次操纵结束时都要求用户再确认一次投放。
UI6-6精度要求与输入方式相称应当
一句话:要对齐到像素的事,别只让手去稳。
适用操纵结果对位置、大小、顺序或数值精度敏感的产品。
规则需要精细定位或小幅调整的操纵,应当提供不依赖手部稳定程度的等价输入(见 gui.manipulation.precision.alternative):步进键、数值输入、对齐与吸附、放大后操纵或按对象选择目标。禁止把达成精度的责任完全交给用户的操作精细度,尤其在触屏与遥控指针等精度较低的输入方式下。精度等价输入的存在不替代 UI6-1 的等价路径要求,两者可以由同一机制满足。
边界条件本条不要求所有操纵都提供数值输入——对精度不敏感的操纵(把卡片拖到另一列)不适用。自由创作类工具中操纵的精细度本身就是表达内容时(手绘笔触),该操纵可排除在本条适用范围外并说明理由。
设计应用吸附与对齐是最常见的一种精度补偿,但它同时会让"故意不对齐"变难。提供吸附时应当一并提供临时关闭吸附的方式,以及精确到数值的输入通道。
验证示例
- 用户侧:在触屏上把一个元素调整到特定数值,记录需要多少次尝试。
- 实现侧:核对精度敏感的操纵是否存在数值或步进等价通道。
反例做不到——裁剪框只能靠拖动手柄调整,在触屏上永远差几个像素,且没有数值输入;做过头——取消全部吸附与辅助线,要求用户逐个输入坐标完成排版。
依据与参考靶区尺寸与拖动动作的替代要求同样适用于精度补偿的判断(R07);平台指南对吸附与步进调整有相关建议(R10、R12)。
4. 术语和定义
本章只定义本规范内使用且容易产生歧义的词。
| 术语 | 定义 | 关键边界 |
|---|---|---|
| 直接操作 | 用户对界面上可见的对象直接施加动作,动作的结果立即可见且可逆的交互方式。 | 是一种交互性质,不是一类控件。界面上有可拖动的方块不等于实现了直接操作;结果不可见或不可逆时,直接操作的前提就不成立。 |
| 对象 | 界面中用户可以指认、可以对之下达命令的那个东西。 | 是产品概念,不是控件实例。一段选中的文字、一个未保存的画布区域同样是对象。对象须具有跨视图变化稳定的身份。 |
| 可操作性 | 一个元素能否被用户施加动作,以及这一点是否可被感知。 | 与可见性、当前可用性是三件事:看得见不蕴含能操作,能操作不蕴含此刻可用。 |
| 选区 | 当前被指定为后续命令作用对象的对象集合。 | 是显式维护的产品状态,不是控件内部变量。由用户指定建立,不由滚动、悬停或未声明为选择动作的点击推定。 |
| 焦点 | 当前接受键盘输入的位置。 | 与选中、悬停语义不同,不得互相替代。移动、进入、退出与返回均须可预期。 |
| 受理 | 系统已接收用户的输入这一事实。 | 不承诺结果。必须区分接收位置与执行阶段,结果可以尚待结算或无法核实。 |
| 乐观更新 | 在服务端确认之前先呈现预期结果的做法。 | 是一种呈现策略,不是一种完成证明。采用它就必须一并定义失败后的回滚范围与告知方式。 |
| 可逆性 | 一次操作在执行之后能被退回到执行前状态的程度。 | 需分别判断本地状态与对外副作用。本地状态回滚不蕴含对外副作用已收回。 |
| 撤销 | 把一次已完成的用户操作退回的能力。 | 单位是用户可识别的一次操作,不是内部事务。与"回退导航"是两件事,不共用入口。 |
| 草稿 | 用户已输入但尚未提交的内容。 | 可在本机或远端持久化,但不因此完成业务提交。它的保存策略与保留期限须声明,不保存也须提前说明。 |
| 保存语义 | "已保存"这一表述所对应的实际状态层级。 | 以存储位置、持久化确认、业务结果与对外效果分别建模;同一文案须对应同一事实条件。 |
| 操纵 | 用连续动作直接改变对象位置、大小、顺序或归属的交互。 | 是输入方式,不是功能。预览取消清除本次未提交变化;持续生效动作分别定义结束和补偿。 |
| 等价路径 | 在不使用某种输入方式或某种动作的前提下,完成同一任务的另一条路径。 | 判据是任务能否完成,不是动作能否复现。用键盘模拟指针移动不构成等价。 |
| 核心任务清单 | 产品主要成果及其完成、恢复和退出所需的任务集合。 | 完整支持须覆盖全部;限定支持须列明子集。缺这份清单时,"支持某种输入方式"无法被检验。 |
附录 A:故障注入验证清单与分类检验
本清单用于检验条款是否真的生效,不新增义务。逐项注入,记录系统的实际行为;记录"不适用"是合格结果,记录"没测"不是。
A.1 对象与选区
| 注入 | 期望行为 | 相关规则 |
|---|---|---|
| 列表刷新或重新排序后,重放上一条命令 | 作用于同一个对象,而不是同一个位置 | UI1-1、UI1-5 |
| 关闭全部悬停样式后渲染界面 | 可操作元素仍可辨识 | UI1-2 |
| 对每一类不可用状态请求解释 | 给出原因与恢复条件,且与实际拦截判定同源 | UI1-3 |
| 选中若干对象后滚动至看不见它们 | 仍可知道选了什么、选了几个 | UI1-4 |
| 使用"全选"后改变筛选条件再执行操作 | 实际作用范围与提交前呈现的范围一致 | UI1-4、UI1-5 |
| 后台数据变更使部分选中对象消失 | 范围变化被告知,不静默增减 | UI1-5 |
| 在已有选区的列表上仅移动键盘焦点 | 选区不被意外改变,或该耦合已声明 | UI1-6 |
A.2 后果与可逆
| 注入 | 期望行为 | 相关规则 |
|---|---|---|
| 对每个不可逆操作,检查提交前的信息 | 影响范围与不可逆性均已呈现 | UI2-1、UI2-4 |
| 清点全部删除类操作 | 低后果且可靠可恢复的不叠加无收益确认,重大影响与不可逆操作有相称确认 | UI2-2、UI2-4 |
| 执行一次复合操作后按一次撤销 | 回到操作前,不停在中间态 | UI2-3 |
| 在确认对话出现时直接按回车 | 触发的是安全动作 | UI2-5 |
| 撤销时注入下游拒绝回滚的响应 | 呈现未撤销的部分与补救路径,不显示"已撤销" | UI2-6 |
| 撤销一次已对外发送的操作 | 不把界面回退表述为对外副作用已收回 | UI2-6 |
A.3 反馈与状态
| 注入 | 期望行为 | 相关规则 |
|---|---|---|
| 人为增加网络延迟后执行提交 | 有受理反馈,用户不重复提交 | UI3-1 |
| 构造慢速成功、快速失败与长期排队三种情形 | 三者界面呈现可区分 | UI3-2 |
| 长耗时操作进行中尝试其他操作 | 阻塞范围与可否取消已说明 | UI3-3 |
| 离线或服务端拒绝条件下执行乐观更新的操作 | 明确告知失败,不静默还原 | UI3-4 |
| 20 项批量操作中构造 3 项失败 | 逐项报告,可定位到具体对象与原因 | UI3-5 |
| 执行可撤销操作后等待提示自动消失 | 撤销入口仍可达 | UI3-6 |
A.4 输入与录入
| 注入 | 期望行为 | 相关规则 |
|---|---|---|
| 拔掉鼠标/仅触屏/仅键盘各走一遍核心任务清单 | 完整支持覆盖全部任务;限定支持与所列子集一致 | UI4-1 |
| 关闭悬停与右键后走核心任务 | 入口仍可发现 | UI4-2 |
| 在二合一设备上切换触屏与键鼠 | 选区、草稿与滚动位置保持 | UI4-3 |
| 抽查可操作元素的尺寸决策 | 可追溯到声明的来源与其例外条款 | UI4-4 |
| 在受限输入方式下访问受限功能 | 得到说明与替代路径,入口不静默消失 | UI4-5 |
| 仅用键盘遍历含自定义控件的区域 | 没有无法进入或无法离开的区域 | UI4-6 |
| 填写到一半让会话过期后重新登录 | 内容仍在,回到原处 | UI5-1 |
| 逐字符输入一个最终合法的值 | 中途不判错 | UI5-2 |
| 逐条检查错误信息 | 含哪里错、为什么、怎么改 | UI5-3 |
| 提交时注入服务端错误 | 内容完整保留,可原地重试 | UI5-4 |
| 打开表单不作修改直接离开 | 不被拦截 | UI5-5 |
| 断网条件下编辑内容 | 保存文案与实际状态档位一致 | UI5-6 |
A.5 直接操纵
| 注入 | 期望行为 | 相关规则 |
|---|---|---|
| 分别只用键盘和只用单指针点按走完全部适用拖动功能 | 均可完成 | UI6-1 |
| 把对象停在容器边界、列表项之间与非法区域 | 三处表达可区分,且含结果预览 | UI6-2 |
| 同列表内、跨列表、跨项目各拖一次 | 移动或复制语义在松手前可见且与结果一致 | UI6-3 |
| 完成一次跨容器拖放后按一次撤销 | 一步回到原容器原位置 | UI6-4 |
| 拖起后按取消键/在非法目标松手/拖出窗口 | 三种情形均无变化,无残留 | UI6-5 |
| 操纵过程中对象被他人删除 | 告知中断、保留真实删除事实,无法核实的结果标记待核对 | UI6-5 |
| 在触屏上把元素调整到特定数值 | 存在数值或步进等价通道 | UI6-6 |
A.6 并发、未知与输入边界
| 注入 | 期望行为 | 相关规则 |
|---|---|---|
| 远端写入成功但响应丢失 | 保留结果未知,经核对或防重保障后处理,不直接重发 | UI3-2、UI3-5 |
| A 编辑失败晚于 B 编辑成功到达 | 只处理 A 的贡献,B 保留;不能安全合并时呈现冲突 | UI3-4 |
| 保存 A 期间输入 B,随后收到 A 的保存回执 | B 不被标成已保存 | UI5-6 |
| 打开模态、删除其触发对象后关闭 | 焦点回到有意义的位置,背景不残留禁用或焦点陷阱 | UI4-6 |
| 指针按下后移出再释放/系统取消指针 | 不意外提交,不残留按压或拖动态 | UI4-7、UI6-5 |
| 输入法选词 Enter、取消候选 Esc | 仅完成对应输入动作,不误提交或关闭 | UI5-7 |
| 旧异步校验响应晚于新输入到达 | 不覆盖新输入的校验状态 | UI5-2 |
| 只用读屏接收批量结果 | 结果及恢复入口可感知,更新不抢焦点 | UI3-1、UI3-5 |
| 使用相同操作身份重试部分成功的批次 | 已成功项不重做,未知项先核对 | UI3-5 |
A.7 分类检验
用于检验第 1 章的切分是否成立:取 10 至 15 条具体要求(可来自本规范条款,也可来自真实评审意见),让至少三名未参与撰写的评审者独立判断其归属原则。归属分歧集中在某两条原则之间,说明这两条原则的规范对象没有切开——此时应当调整原则,而不是增设中间层或说明。已知需要重点检验的两处见第 1 章的明示(UI1 与 UI3、UI4 与 UI6)。评审人数与分歧阈值是本规范建议的内部检查法,不是经文献验证的标准。
附录 B:论据边界与来源类型
B.1 约束词的判据
标「必须」的唯一依据是:缺了它,某条对用户的承诺会在可预见的情境下失效。下列三类论据提供不同支持,不是三种独立的强制性来源;实现参考本身不足以决定标「必须」——
| 来源 | 说明 | 例 |
|---|---|---|
| 成文标准的既有条款 | 已有标准对该情形作出要求,本规范把它写进设计语言,不构成符合性判定 | UI4-4 的靶区来源、UI6-1 的拖动替代、UI2-4 涉及的可撤销或可核对要求 |
| 有证据的失效 | 已有研究、启发式清单或公开的失败记录表明该承诺会失效 | UI3-2 的阶段与结果分离、UI5-2 的校验时机、UI3-5 的错误可定位 |
| 从承诺反推 | 产品既然作出该承诺,缺了这项机制承诺必然落空 | UI5-6(“已保存”必须解析到事实条件)、UI3-4(乐观更新必须能回滚)、UI6-5(放弃必须不留残余) |
标「应当」的七条(UI1-6、UI2-5、UI3-3、UI3-6、UI4-5、UI5-5、UI6-6)都是取舍问题而非底线问题:偏离可能有正当理由,但要留痕并接受同样的验证。其中 UI1-6 允许单选情形下选择随焦点移动,UI6-6 允许创作类工具排除手部精细度本身即表达内容的操纵——这两处的例外范围最容易被扩大使用。
B.2 本规范证据最薄的三处
明确列出,不用条款语气掩盖:
- UI3-1、UI3-3 的时间门槛没有本规范可核验的通用值。关于响应时间的经典分档被广泛引用,但它并未针对当前的设备、网络与界面形态重新验证,也不能直接转写为各类操作的通用门槛。本规范因此只要求"由产品按目标场景与人群测定并记录依据",不给数值——这也是本规范中最容易被形式化应付的一条。
- UI2-2"撤销优先于确认"是设计主张,不是实证结论。现有来源支持"为误操作留出退出口"与"错误预防优于错误提示"这两个方向,但本次检索未发现能证明"撤销普遍优于确认"的跨产品对照研究。本条的强度来自后果分析(确认要求用户在注意力最低的时刻作判断),不来自实验证据。
- UI4 的输入对等以核心任务清单为锚点,而清单本身由产品定义。这使得本组规则的严格程度取决于产品把哪些任务写进清单。UI4-1 给出主要成果及创建、修改、提交、恢复、退出的纳入依据;仍须用真实任务观察核对清单是否漏掉关键工作,不能只靠自我声明。
B.3 本规范未做的事
不给控件清单,不给视觉规范,不给栅格与间距,不给动效时长,不设跨平台统一靶区数值,不给组件 API,不给状态机实现,不给拖放库的选型建议,不作无障碍符合性判定。这些是产品、设计系统与专项评估的决定;本规范只规定这些决定必须被作出、必须可被检验,以及哪些取值不被允许。
B.4 来源
完整的来源对照、核验状态与检索记录见 reference.md。规范中的条款不因为某个平台这样做过就成立;平台做法是"这类机制在真实产品中可行"的证据,不是"应当这样要求"的依据。多个平台指南之间存在不一致时,本规范不作优劣排序,只取其共同支持的行为性质。
附录 C:从场景到验收的最小设计记录
本附录是应用方法,不新增规则。按一个实际任务填写,避免按控件数量扩充文档。
| 要回答的问题 | 最小交付 |
|---|---|
| 用户完成什么 | 任务起点、完成结果、主要输入方式;不用“优化体验”代替成果 |
| 动哪些对象 | 对象身份、选择范围、命令对象与关键前置条件 |
| 何时产生后果 | 预览、提交、受理、结果确认的分界;可取消和可撤销的范围 |
| 工程提供什么事实 | 对象身份、操作身份、执行依据、逐项结果、草稿保存回执及各自来源 |
| 用户如何理解 | 默认显示什么、什么可展开核对、什么需要人决定;附正常与失败文案 |
| 哪些决定可复用 | 适用 Token 的最终值、决定方、理由、依赖与生效条件;不适用项写明条件 |
| 如何验证 | 正常、失败、未知、并发、取消、恢复及“过度打断”成对用例 |
贯穿场景:将选中的 20 张卡片移动到归档列。工具栏显示“移动 20 项”,可核对跨页选择;拖放预览显示目标与移动语义,同时有键盘及点按可用的“移动到”菜单。释放或确认目标时冻结对象范围;远端未确认前显示“正在移动”,不用“已完成”。17 项成功、2 项拒绝、1 项结果未知时,按三组汇总且可定位每项;只对已核实失败且满足重试条件的项开放重试,未知项先核对。撤销归属于本次操作并保护后续编辑;不能全部还原时逐项说明。普通移动不因这些保障多出反复确认。
验收证据分开保存:文档检查证明定义完整;故障注入证明机制在测试条件下成立;真实任务测试证明用户能理解和完成。不可用综合分抵消错对象、丢输入、未知结果被说成成功、重复外发等底线失败。“未测”不算通过;不适用须能复核。另记录正常路径的点击数、完成时间、错误恢复耗时和无收益打断,检验防错是否增加了不必要负担。
实施验收场景
以下场景把已有条款转成可复核的验收输入,不另设通用性能阈值。按产品适用能力选取,补充真实设备、用户、输入序列和证据;不适用记录原因,未执行不得记为通过。
| 条款 | 测试输入与异常 | 预期行为与失败判据 |
|---|---|---|
| UI1-5 | 选中 A 后刷新列表,使 B 进入 A 的原位置。 | 命令仍作用于 A 或明确失效,不作用于 B。 |
| UI6-1 | 禁用拖动,仅使用单次点击完成移动;再独立用键盘完成。 | 两条路径分别完成相同任务,保持相同权限与提交含义。 |
| UI3-4 | 乐观更新后服务端拒绝部分项目。 | 定位失败项目并保留其输入;不回退其他已成功项目。 |
每个场景分别核对配置的有效值、执行记录与用户可理解的结果。保留版本、目标、事件时点、失败范围和恢复结果;外部结果未知不填作成功或失败。
使用说明
本字典记录图形界面的行为决策:对象与选区的范围、撤销承诺、状态表达、输入路径、草稿和操纵语义。配套设计规范使用,字段以 gui. 为前缀。它是可复用的行为配置契约,不是视觉样式表,也不声称可直接导入 DTCG 工具;颜色、尺寸等表现值可通过有类型的引用绑定,行为枚举与策略引用不能冒充标准颜色或尺寸类型。
先作设计决定,再选择适用字段。字段不是用户设置清单;必选项也可以由产品预设解析。当前对象 ID、当前进度、错误原因与执行结果是运行事实,不存入 Token。策略决定“如何处理”,不改变“已经发生了什么”。
一条贯穿全表的读法:本字典中的取值是"这个界面对用户作出了什么承诺"的声明,不是"实现用了哪个控件"。部分能力字段的合法取值里有“不提供”或“关闭”,那不是降级方案——对很多产品来说它是正确答案;真正不被允许的,是提供了能力却不声明其边界(拖放没有等价路径、乐观更新没有回滚语义、"已保存"指不清楚是哪一层)。
七类速览
| 类别 | 前缀 | 必选 | 可选 | 合计 | 负责什么 |
|---|---|---|---|---|---|
| 对象 | gui.object | 3 | 3 | 6 | 什么可操作、身份和作用范围 |
| 选区 | gui.selection | 3 | 4 | 7 | 选择范围及视图变化后的保持 |
| 可逆性 | gui.reversibility | 3 | 5 | 8 | 撤销范围、期限与确认 |
| 反馈 | gui.feedback | 3 | 9 | 12 | 事实呈现、未知、并发与重试 |
| 输入 | gui.input | 3 | 7 | 10 | 支持范围、焦点、键盘与指针 |
| 录入 | gui.entry | 3 | 7 | 10 | 草稿、校验、保存与输入辅助 |
| 操纵 | gui.manipulation | 3 | 5 | 8 | 替代路径、预览与生效边界 |
合计 61 项:21 项必选,40 项可选。可选表示按能力启用,不表示启用后可省略依赖。
必选与可选
| 级别 | 含义 | 配置方式 |
|---|---|---|
| 必选 | 在该字段的适用条件成立时必须明确的基础决策:无默认则行为无定义——不声明选择模型就无法判断一次操作作用于谁,不声明保存语义就无法判断"已保存"承诺了什么。 | 可以继承产品预设或设计系统预设,也可以用合法的"不提供""关闭"取值表达限制;不要求用户逐项填写。完全没有图形界面的产品(纯命令行、纯语音、纯 API),整份字典记"不适用"即可。 |
| 可选 | 仅在特定能力或差异化需求下采用的参数。 | 无对应能力时不配置;启用能力后,必要依赖必须有明确值或可执行的继承规则(见第八节)。 |
必选只在其适用条件成立时要求解析。不适用须有可检查的条件与理由,且不参与值的继承;缺失与未知都不等于不适用——有该能力却漏配必须判为配置无效,不得以"不适用"回避。适用条件按字段表的"适用条件与作用"列解析,常见情形:
| 情形 | 随之不适用的字段 |
|---|---|
selection.model 取"不可选" | selection.visibility、persistence.on_view_change、limit、include_filtered、focus.coupling、actions.scope |
manipulation.drag.mode 取"不提供" | drop.preview、cross_container.semantics、drag.alternative;取消、撤销与精度字段仍按其他连续操纵是否存在判定 |
| 仅在同一容器内排序,不存在跨容器投放 | cross_container.semantics |
| 界面不接受用户录入 | 草稿、校验、输入辅助等字段;若仍有保存、同步或提交文案,entry.save.semantics 仍适用 |
| 全部操作结果同步可见且不可失败(纯本地) | feedback.states、ack.mode、optimistic.mode |
对象、选区、操作、反馈与操纵的边界
| 对象 | 负责什么 | 关键边界 |
|---|---|---|
| 对象 | 界面中用户可以指认、可以对之下命令的那个东西:一行、一张卡、一个文件、一个字段。 | 是产品概念,不是控件。"看得见"与"可操作"是两件事:可见性由布局决定,可操作性必须由独立的感知线索承载。 |
| 选区 | 当前被指定为后续操作作用对象的对象集合。 | 是有状态的产品对象,不是控件的内部变量:它有明确的建立、扩展、清除时机,在排序、筛选与刷新之下有确定的存续语义,并且必须可核对。 |
| 操作 | 用户发出的一次改变系统状态的命令。 | 它的作用对象、影响范围与可逆性,都要在提交这一步之前成立,而不是在结果出来之后解释。 |
| 反馈 | 系统对一次操作作出的可感知回应。 | 阶段、结果与事实依据是不同维度,不能靠更换同一段动画来推定。"界面变了"不等于"服务端收到了","没报错"不等于"成功了"。 |
| 操纵 | 用户用连续动作直接改变对象位置、大小、顺序或归属的交互:拖放、缩放、框选、手写。 | 是一种输入方式,不是一种功能。除输入路径本身不可替代的任务外,功能须有等价路径;预览取消清除本次改动,持续生效控件按其提交策略处理。 |
同一个界面可以在对象层允许多选、在可逆性层禁止撤销、在操纵层不提供拖放——三者各自裁决,不因其中一项开启而放宽另一项。"用户能看到一个变化"与"这个变化已经生效"是两件事:前者由 feedback.ack.mode 表达,后者由 entry.save.semantics 与 feedback.states 表达,后者不得仅由前者推定。
字段读取约定
每节前缀与表中的字段拼接为完整名称,例如 gui.selection 与 persistence.on_view_change 组成 gui.selection.persistence.on_view_change。七类统一使用 级别、设计决定、字段、类型与合法取值、适用条件与作用 五列。
配置键按"产品预设 → 对象类型或功能 → 操作类别 → 适用场景"四层绑定,逐层可覆盖;运行对象的 ID 与其当前状态不写进本字典。同一产品内可逆编辑与不可逆发送分别取值,互不污染。
数值型时长写成“带单位的数值 + 起算事件 + 是否续期 + 到期处理”;事件型期限与持续保留另行明示:
reversibility.undo.ttl:正时长、明确终止事件或经证明的持续可恢复条件;按已声明的可撤销起点起计,通常自操作确认完成或进入可撤销队列起计;不得超过实际可恢复期;缺失不等于 0(缺失是配置无效);不得通过缩短配置回收已经向用户承诺的窗口。entry.draft.ttl:正时长、明确终止事件或带删除机制的持续保留;起算点为最近一次实质编辑;读取不续期;须写明到期处理,以及是否另有用途上限。feedback.notice.duration:正时长或"不自动消失";自提示呈现起计;撤销、重试与详情入口不随其消失。
上限类字段写整数或"无额外上限":selection.limit 的容量上限与 include_filtered 的作用范围是两个决定,不设容量上限不推出"全选"的范围可解析。
尺寸引用必须包含测量单位、实际命中范围与依据来源,范围引用可解析到明确的视图、作用域或对象类型。集合不默认全选,逐项写明其最小包含条件。多个硬限制同时生效时取共同允许的范围,不按"后配置覆盖前配置"放宽保护;视图级配置不得放宽文档级或账号级的保护设定。
未知按保守的一档决定当前行动,但不得被写成确定的事实。未知输入方式按"该方式下不可用"处理并说明;未知投放语义按"不执行"处理;未知可逆性不承诺可撤销;后果本身也未知时先核对,不以确认放行。
远端写入结果未知是例外中的重点:不得解析为"尚未提交",也不得解析为"失败"——保留"结果待核对",提供核对路径,并按 feedback.unknown.action 声明的处置(核对/暂停相关提交/转人工)执行。保守的行动策略与对事实的断言是两件事。
类型、引用与解析
- 枚举精确取一个合法值;集合无重复项,空集合必须符合该字段条件。禁止把任意自然语言解释当成额外合法值。
- 引用必须解析到具体契约及其类型,例如对象身份规则、字段映射或恢复策略。引用失效、循环继承、同一绑定层发生冲突时,配置无效;禁止静默选择“最后加载”的值。
- 每项保存最终值、适用条件、决定方、理由、依据与生效条件。无通用默认值的字段必须显式决定;“按平台惯例”要能指向实际采用的行为。
- 先判适用,再解析继承和覆盖,随后检查类型、硬限制、联动依赖与运行机制。底线不能作为布尔开关关闭;配置通过也不能代替机制验证。
- 时长用
{value, unit, starts_on, renew_on, expires_to},其中unit为ms、s、min、h或d;事件型期限用{until, expires_to}。缺失、零、不适用与无期限不同;无限保留须有明确依据和删除机制。
一、对象:什么是可操作的、操作作用在谁身上、不能操作时怎么说
前缀:gui.object
| 级别 | 设计决定 | Token 字段 | 类型与合法取值 | 适用条件与作用 |
|---|---|---|---|---|
| 必选 | 可操作性的感知线索 | affordance.cues | 集合:形状与边界、颜色对比、图标、文案、位置约定、仅在悬停时出现。"仅在悬停时出现"不得作为唯一项;集合须在产品声明支持的每种输入方式下成立。 | 决定用户凭什么判断一个东西能不能操作;不靠试探发现(对应 UI1-2)。 |
| 必选 | 对象身份 | identity.key | 引用:每类可操作对象在刷新、排序、筛选与分页之后仍可解析的稳定标识来源。位置序号不作为身份。 | 决定"同一个对象"在视图变化前后是否还是同一个;选区存续与撤销定位都依赖它(对应 UI1-1、UI1-5)。 |
| 必选 | 不可用状态的表达 | unavailable.mode | 枚举:隐藏/显示原因与恢复条件/安全概括说明与求助路径。第三档须有信息披露限制的依据,不允许“显示但无解释路径”。 | 存在受限对象时必选;完全不产生不可用状态时不适用(UI1-3)。 |
| 可选 | 不可用原因的判定来源 | unavailable.reason.source | 引用:判定该对象当前不可用的条件来源。呈现给用户的原因与实际执行拦截的判定须来自同一处。 | 存在权限、状态或配额限制时配置;两处判定不一致时用户会收到与实际不符的解释(对应 UI1-3)。 |
| 可选 | 限制类型 | restriction.kind | 本产品支持表达的限制类型集合(内容只读/权限不足/当前状态不允许/能力不支持/配额或期限限制)加上其判定与呈现映射的引用:同一对象可能同时命中多项(既只读又权限不足),映射须规定如何取舍与排序,以便给出真实且可行动的说明。本字段不保存某个实例当前的唯一限制原因——那是运行事实。 | 需要区分"改不了"的不同成因时配置;不同成因的恢复路径不同,混为一档会让恢复条件无法表达(对应 UI1-3)。 |
| 可选 | 作用范围的呈现 | action.scope.display | 可组合的结构:count(受影响对象数)+scope_note(范围口径:仅当前页/当前筛选结果全部/显式选定且跨筛选,并注明是执行时快照还是动态查询)+verify_entry(可展开的对象清单或可核对的查询入口)。作用于多个对象且含不可逆后果时,三项均须具备——只给数量不满足。总数未核实且会影响用户判断时,须先核对或缩小到已知对象。 | 提交前让用户知道这一步动了谁(对应 UI2-1)。 |
边界:对象身份决定"是谁",感知线索决定"能不能动",限制类型决定"为什么现在不能动"。三者独立:可见不蕴含可操作,可操作不蕴含当前可用。本节不规定控件形态,只规定这些判断必须可解析。
二、选区:能选几个、当前选中什么、视图变了选区还算不算数
前缀:gui.selection
| 级别 | 设计决定 | Token 字段 | 类型与合法取值 | 适用条件与作用 |
|---|---|---|---|---|
| 必选 | 选择模型 | model | 枚举:不可选/单选/多选/区间加多选。多选一档须一并明确扩展与清除选区的操作。 | 明确一次操作可以作用于几个对象;这是判断"这条命令动的是谁"的前提(对应 UI1-4)。 |
| 必选 | 选区可见性 | visibility | 枚举:对象上的选中标记/标记加计数摘要/标记、计数与可展开清单。多选且选区可能超出当前可视范围时不得取第一档。 | 决定用户能否在动手前核对选区(对应 UI1-4)。 |
| 必选 | 视图变化后的选区语义 | persistence.on_view_change | 枚举:按 object.identity.key 保持并呈现范围变化/清空并告知。不提供"按位置保留"或"静默保留"的取值。 | 排序、筛选、分页、刷新之后选区所指的对象不得静默改变(对应 UI1-5)。 |
| 可选 | 选区上限 | limit | 正整数或"无额外上限",及达到上限时的呈现与后续操作。容量上限与作用范围是两个决定:不设容量上限不代表"全选"的实际作用范围已可解析,后者由 include_filtered 与 object.action.scope.display 承担。上限由产品按实际操作规模与性能测定并记录依据,本字典不给数值。 | 存在批量操作时配置;容量依据与范围口径须分别核对(对应 UI1-4)。 |
| 可选 | 筛选外对象是否计入 | include_filtered | 枚举:仅当前页内的对象/当前筛选结果的全部对象(含分页之外)/用户显式选定且跨筛选的对象集合。后两档是不同的后果,不得合并为一档;均须在提交前显式呈现范围与总数,并按 action.scope.display 注明快照或动态查询口径。 | 提供"全选"或跨页选择时配置;这是批量操作中最容易与用户理解不一致的一处(对应 UI1-4、UI1-5)。 |
| 可选 | 焦点与选中的关系 | focus.coupling | 枚举:选择与焦点分离/单选情形下选择随焦点移动/按已声明的多选模型处理。每一档须说明方向键、确认键与选择变更的语义。任一档下,普通遍历都不得触发不可逆的业务效果;是否允许自动发起预览类加载,按延迟成本、是否改变对象状态与用户意图分别判定并记录——本字段不把"发起一次预览"一概判为不合法(与 UI1-6 同一口径)。 | 存在键盘或方向键遍历时配置;焦点、悬停与选中是三种语义,合并须是明示的设计决定(对应 UI1-6)。 |
| 可选 | 可作用于选区的操作 | actions.scope | 集合:允许以整个选区为作用对象的操作。未列入的操作只作用于单个对象,不得因存在选区而扩大作用范围。 | 提供多选时配置;防止一条为单对象设计的命令被静默施加到整个选区(对应 UI1-4)。 |
边界:选区是状态,不是控件的内部变量。它的输入是用户的指定,不是系统的推测——不得因为滚动、悬停或未声明为选择动作的点击就把该对象计入选区。选区的可见性与选区的作用范围是两件事:看得见不等于算得清,visibility 管前者,actions.scope 与 include_filtered 管后者。
三、可逆性:撤销管多大范围、哪些回不来、确认到什么程度
前缀:gui.reversibility
| 级别 | 设计决定 | Token 字段 | 类型与合法取值 | 适用条件与作用 |
|---|---|---|---|---|
| 必选 | 撤销能力 | undo.mode | 枚举:不提供/提供且作用于当前视图/提供且作用于声明的作用域。取"不提供"须逐类操作说明理由,不以"实现成本"一句带过。 | 明确撤销是不是这个产品的默认能力(对应 UI2-2)。 |
| 必选 | 不可逆操作清单 | irreversible.actions | 集合:每项含操作名、后果描述、受影响对象类型与是否有替代的可逆做法。空集合须有依据。 | 明确哪些操作做完就回不来;这是确认档位的输入(对应 UI2-4)。 |
| 必选 | 确认档位 | confirm.level | 按操作类别分别赋值的映射(见《字段读取约定》的绑定层级),取值:不确认(低后果且恢复可靠)/复述后果的确认/复述后果并列出受影响对象/要求主动输入以确认。档位由后果严重程度、授权需求与恢复能力共同裁决,不由可逆性单独裁决,也不由弹窗数量决定:低后果、恢复可靠且成本可接受的操作取第一档;需要必要授权、有重大累计影响、恢复不能覆盖全部后果或误操作即造成重要中断的,可在具备撤销能力的同时取更高档并记录理由。同一产品内可逆编辑与不可逆发送各自取值,互不污染。 | 明确"确认"这件事到底承诺了什么(对应 UI2-4、UI2-2)。 |
| 可选 | 撤销作用域 | undo.scope | 引用:撤销记录的边界(视图、文档、会话、账号)、跨会话保持及共享方式。无隐含的“当前视图”默认。 | 提供撤销时配置;需保护后续及他人的有效修改(UI2-3)。 |
| 可选 | 撤销期限 | undo.ttl | 正时长、明确终止事件或经证明的持续可恢复条件;均记录起点、续期与失效行为。不得超过实际恢复能力,不得取零后仍宣称可撤销。 | 提供撤销时须解析期限;不因提示消失而终止(UI2-2、UI2-6)。 |
| 可选 | 撤销粒度 | undo.granularity | 引用:操作分组策略——把系统内部变更归并为"用户可识别的一次操作"的规则。唯一的合法结果是"一次用户可识别的操作对应一步撤销";内部事务可以有多步,但不得暴露为多次必要撤销。"按内部事务分步"不是合法取值,reason 说明不能豁免该禁令;确属用户分别发起的两次独立操作的,按两次操作记录。 | 存在复合操作时配置;粒度与用户心智不一致会让撤销本身变成新的意外(对应 UI2-3)。 |
| 可选 | 破坏性动作的默认值 | destructive.default | 枚举:默认落在不执行破坏动作的一侧/该确认没有破坏侧默认。不提供"默认执行破坏动作"的取值。 | 存在确认环节时配置;默认值与误触路径是同一个问题的两面(对应 UI2-5)。 |
| 可选 | 撤销失败的处置 | undo.failure.mode | 集合:如实说明哪一部分未能撤销、给出可执行的补救路径、保留可核对的记录、标明已外发且不可回收的副作用。不得在未完成撤销时呈现"已撤销"。 | 撤销可能部分失败时配置;对外副作用与本地状态的可逆性不同(对应 UI2-6)。 |
边界:确认管"做之前",撤销管"做之后",两者是替代关系而非叠加关系——能撤销的操作不需要确认,不能撤销的操作靠加弹窗也补不回可逆性。irreversible.actions 是这一节的事实基础:清单不诚实,confirm.level 与 undo.ttl 都会配错。
四、反馈:阶段与结果怎么分、未知与并发怎么处理
前缀:gui.feedback
| 级别 | 设计决定 | Token 字段 | 类型与合法取值 | 适用条件与作用 |
|---|---|---|---|---|
| 必选 | 状态呈现映射 | states | 引用:固定事实词表到文案、可访问状态和可执行动作的映射。阶段为本地接收/排队/执行中/结束/未知;结果为待定/成功/失败/部分成功/已取消/未知。不存在的能力可不适用,但不得删除未知;本字段不存实例状态。 | 异步、后台或可能失败的操作;合法组合见十一节(UI3-2)。 |
| 必选 | 受理反馈 | ack.mode | 枚举:无独立反馈/原位状态变化/原位状态变化加文案。取"无独立反馈"仅在操作结果本身即时可见且不可能失败时成立。 | 明确用户凭什么知道"它收到了";受理不等于完成(对应 UI3-1)。 |
| 必选 | 乐观更新策略 | optimistic.mode | 枚举:关闭(确认后才呈现结果)/开启且失败时回滚并告知。不提供"开启且静默回滚"的取值;开启时须一并声明回滚覆盖的状态范围。 | 明确"界面已经变了"是否代表"服务端已经接受"(对应 UI3-4)。 |
| 可选 | 进行中的信息 | progress.info | 集合,至少含能否取消、阻塞范围、进度依据或剩余量未知。提供取消时还须说明取消请求、实际生效、部分结果及核对路径。无确定比例可用不定进度动画,不得伪造百分比。 | 长耗时操作配置;等待门槛须经场景测定(UI3-3)。 |
| 可选 | 批量结果映射 | batch.result.granularity | 引用:逐对象身份与结果的记录契约,以及成功、失败、未知、取消的汇总规则。必须可展开核对,不能只保留一个整体结论。 | 存在多对象操作时配置(UI3-5)。 |
| 可选 | 失败信息的内容 | failure.content | 集合,最小包含:受影响的对象、失败原因(原因未知时须显式说明"原因未知")、可执行的下一步。部分生效时必须补"已生效的范围";声明可重试时必须补"重试在什么条件下安全"。 | 存在可失败的操作时配置;只说"操作失败"无法支持恢复(对应 UI3-5)。 |
| 可选 | 反馈的可见时长 | notice.duration | 正时长,或"不自动消失"。由产品按目标人群的阅读与操作时间测定并记录依据;撤销、重试与详情入口不得随该提示一同消失。 | 使用提示时配置;提示的存续时间不得成为用户的操作期限(对应 UI3-6)。 |
| 可选 | 结果未知时的处置 | unknown.action | 集合,必须含提供核对路径,可增加暂停相关提交、转人工。任何取值均不得改写未知事实;自动重试另由 retry.policy 限定。 | 远端写入、外部调用或可能丢失回执时配置(UI3-2)。 |
| 可选 | 反馈的位置 | placement | 枚举:操作发生处/固定区域/两者兼有。选择须使反馈在用户当前注视范围内可被发现,不要求全产品统一位置。 | 存在跨区域生效的操作时配置;反馈出现在用户看不到的地方等于没有反馈(对应 UI3-1)。 |
| 可选 | 安全重试 | retry.policy | 引用:操作身份、可重试原因、去重覆盖范围与期限、重试次数上限、未知核对入口。无自动重试取次数 0;窗口不足或身份不可复用时先核对,不重新发起同一副作用。 | 存在可重试写入时配置;禁用按钮不能代替去重(UI3-2、UI3-5)。 |
| 可选 | 并发恢复 | concurrency.policy | 枚举:按操作贡献回退/重取可信状态并合并/暂停冲突项待用户决定;附判定与保留输入的策略引用。禁止整份旧快照覆盖后续有效编辑。 | 异步编辑、乐观更新或并发撤销时配置(UI2-3、UI3-4)。 |
| 可选 | 反馈播报 | announcement.policy | 映射:状态类别→播报优先级、合并条件与持久入口。普通进度不抢焦点;失败、未知、需人决定的结果不可丢失。 | 提供动态状态消息时配置(UI3-1、UI3-6)。 |
边界:ack.mode 管"它收到了没有",states 管"它进行到哪一步了",optimistic.mode 管"我看到的是结果还是预期"。三者独立:即时的界面变化不构成受理证明,受理不构成完成证明,完成呈现不构成对外副作用已生效的证明——把三者合并成一个"加载动画",等于同时失去三处判断。
五、输入:支持哪几种输入、悬停能不能承载信息、换手之后状态还在不在
前缀:gui.input
| 级别 | 设计决定 | Token 字段 | 类型与合法取值 | 适用条件与作用 |
|---|---|---|---|---|
| 必选 | 输入方式支持声明 | methods | 映射:每种输入方式→{支持档位、任务范围}。方式包括鼠标或触控板、触屏、物理键盘、笔、手柄、语音或开关设备;档位为完整支持/限定范围支持。完整支持覆盖全部 core_tasks;限定支持须关联 capability.gaps。 | 所有图形界面;限定支持不能豁免实际适用的键盘与拖动替代义务(UI4-1)。 |
| 必选 | 核心任务清单 | core_tasks | 引用:主要用户成果及其创建、选择、修改、提交、恢复、退出路径。逐任务写明成功标准;不提供的能力记录理由,不得用“主要功能”概括。 | 所有图形界面;防止靠缩减清单掩盖输入缺口(UI4-1)。 |
| 必选 | 悬停内容的角色 | hover.role | 枚举:无信息/补充信息且有无悬停等价入口。补充内容须有关闭、移入阅读与保持语义,适用例外记录理由。 | 无悬停内容可取无信息(UI4-2)。 |
| 可选 | 靶区的测量契约 | target_size.ref | 引用:{输入方式、宽高、单位、实际命中区域、间距判据、来源条款、适用例外}。Web 采用 2.5.8 时为 24×24 CSS px 或其例外;pt、dp、CSS px 不互换,视觉图标不等于命中区域。 | 有指点输入时配置;值必须可测量,不能只写“符合标准”(UI4-4)。 |
| 可选 | 切换输入方式时的保持项 | switch.preserved | 集合。其中选区、草稿、滚动位置、展开与折叠状态、进行中的操作五项是固定保护项,不可删减;集合只用于追加其他需要保持的项(如当前作用对象)。"已告知状态被重置"不构成本字段的满足。 | 同一设备上多种输入方式并存时配置;按内容锚点保持阅读位置,不强制保持滚动像素(对应 UI4-3)。 |
| 可选 | 能力差异说明 | capability.gaps | 集合:每项含受限的输入方式、受限的功能、替代路径、该限制的理由。不得以空集合表示"全部对等"而无核对记录。 | 某些功能确实无法在全部输入方式下对等时配置;差异要明示,不静默降级(对应 UI4-5)。 |
| 可选 | 右键与长按的角色 | context_menu.role | 枚举:无/快捷入口且有无需右键或长按的等价入口。常驻“更多操作”按钮可承载命令,无需全部平铺。 | 提供上下文菜单时配置(UI4-2)。 |
| 可选 | 指针提交与取消 | pointer.policy | 映射:操作类别→释放激活/释放反转/可取消或撤销的连续动作/必需按下触发。附目标外释放、指针取消与拖后点击的处置;必需项须有理由。 | 解释指针动作时配置(UI4-7)。 |
| 可选 | 焦点流转 | focus.policy | 引用:进入位置、关闭返回、触发者消失后的去向、模态边界及内容更新后的焦点目标。无模态时不要求模态分支;不能配置关闭焦点可见性。 | 可聚焦控件及动态界面配置(UI4-6)。 |
| 可选 | 键盘与快捷键 | keyboard.policy | 引用:控件键位、进入退出、作用域、冲突处理及单字符快捷键关闭/改键/聚焦限制。输入法和文本编辑优先于全局快捷键。 | 存在可操作控件时配置(UI4-6、UI5-7)。 |
边界:输入对等的判据是同一个任务能不能完成,不是同一个手势能不能复现——触屏上没有悬停、键盘上没有坐标、手柄上没有精确指点,要求它们模仿彼此的动作是把对等做反了。键盘、焦点、指针与辅助技术路径必须分别验证,能力声明不能代替实际可达性。
六、录入:草稿丢不丢、什么时候判错、"已保存"指哪一层
前缀:gui.entry
| 级别 | 设计决定 | Token 字段 | 类型与合法取值 | 适用条件与作用 |
|---|---|---|---|---|
| 必选 | 草稿保存策略 | draft.mode | 持久化位置集合:空集合(不持久化)/本机/远端/两者。取空集合须在用户开始投入前说明,不放在提交失败之后才告知;空集合只限制崩溃、关闭与跨会话之后的恢复承诺,不解除"同一会话内不因系统行为丢失内容"这一项。"远端保存但本机不留持久副本"是合法配置。出于安全或合规不得留存的字段逐项列出理由。 | 明确用户已经输入但尚未提交的内容会不会留下(对应 UI5-1)。 |
| 必选 | 校验时机 | validation.timing | 映射:字段或字段类型→提交时/字段完成输入后/输入过程中。输入中只作不会随后续输入变对的错误判断;组合输入不判终局错误,旧异步响应不覆盖新值,纠正后及时清除已有错误。 | 有校验时必选;“停顿”不能单独证明已完成输入(UI5-2)。 |
| 必选 | 保存语义 | save.semantics | 文案到事实条件的映射引用,事实按五个维度分别记录:存储位置、本地持久化是否已确认、远端持久化是否已确认、业务提交结果、对外效果的证据。产品中每一处"已保存""已同步""已完成"文案都须解析到该映射上的一组具体条件——"服务端已有草稿但业务未提交"与"业务已生效"必须可分辨。本字段存映射,不存某次运行的状态;并非每个界面都展示全部维度。 | 明确"已保存"到底承诺了什么;这是本节最容易被含混的一处(对应 UI5-6)。 |
| 可选 | 草稿保留期限 | draft.ttl | 正时长、明确终止事件,或带删除机制与依据的持续保留。起点为最近实质编辑,读取不续期;到期行为和提前告知须明确。 | draft.mode 为非空集合时配置(UI5-1)。 |
| 可选 | 错误呈现位置 | error.placement | 集合:字段处、页面汇总处、提交入口附近。含多个错误时须能从汇总定位到具体字段,且定位不依赖用户自行查找。 | 存在多字段表单时配置(对应 UI5-2)。 |
| 可选 | 错误信息的内容 | error.content | 集合,最小包含:哪里错、判错依据、怎么改成对的。系统可自动修正的须另补"是否已自动修正及如何撤回"。"格式不正确"单独出现不满足本项。 | 存在校验时配置;错误信息的作用是支持恢复,不是宣布失败(对应 UI5-3)。 |
| 可选 | 提交失败后的内容保留 | submit.failure.retain | 枚举:保留全部已输入内容/保留除受限字段外的全部内容。不提供"清空"的取值;受限字段须逐项列出并说明理由。 | 存在可能失败的提交时配置;清空重填把系统的失败转嫁给用户(对应 UI5-4)。 |
| 可选 | 离开确认条件 | leave.guard | 引用:实质未保存变更判据、保存/放弃/取消行为和环境限制。应用内导航提供三种可分别执行的决定;浏览器关闭只使用平台可用提示,不假设可定制按钮。 | 离开会丢失内容且产品使用拦截时配置;不能替代草稿保存(UI5-5)。 |
| 可选 | 输入辅助 | input.policy | 引用:组合输入、粘贴、自动填充、输入目的及格式规范化的处理;限制按字段记录,默认允许平台输入辅助。不得将组合选词视为提交。 | 接受文本或凭据时配置(UI5-7)。 |
| 可选 | 重复资料复用 | reuse.policy | 枚举:自动带入且可修改/从已提供内容选择/确有必要重新输入。最后一档须绑定任务实质、安全必需或数据失效依据。 | 同一流程重复使用资料时配置(UI5-7)。 |
边界:草稿保存管"东西还在不在",保存语义管"这件事算不算办成了",两者不得互相推定——自动保存不构成业务提交,提交成功也不构成对外副作用已完成。校验时机与错误内容是两件事:时机管什么时候说,内容管说了之后用户能不能改对。
七、操纵:拖放有没有替代路径、放下会发生什么、中途放弃留不留痕
前缀:gui.manipulation
| 级别 | 设计决定 | Token 字段 | 类型与合法取值 | 适用条件与作用 |
|---|---|---|---|---|
| 必选 | 拖放能力 | drag.mode | 枚举:不提供/提供且存在非拖放的等价路径。不提供"仅拖放"的取值。 | 明确拖放是不是某项功能的唯一通道(对应 UI6-1;靶区与拖动动作的无障碍要求另见 reference.md 第三节)。 |
| 必选 | 投放预览 | drop.preview | 集合,至少包含合法/非法目标辨识,以及结果位置或结果语义表达之一。当前目标失效、权限变化或对象变动时重新核对;不将高亮当作提交完成。 | 提供投放时必选(UI6-2)。 |
| 必选 | 跨容器语义 | cross_container.semantics | 枚举:移动/复制/由用户在操纵过程中选择。所取语义须在松手之前可见;取第三档时须声明未作选择时的默认档。 | 明确把东西拖到另一个地方之后,原处还剩不剩(对应 UI6-3)。 |
| 可选 | 非拖放的等价路径 | drag.alternative | 集合,每项含:所对应的功能引用、入口引用、可用的输入方式与操作约束。drag.mode 为“提供且存在非拖放的等价路径”时不得为空集合,且必须至少含一条不要求拖动、不依赖路径型手势的单指针路径;仅含键盘命令不满足——键盘路径与单指针路径分别成立、分别验证。拖动动作本身即任务实质内容的(自由手绘、签名),逐功能记录例外理由。 | 提供拖放时必须配置(见第八节);等价路径的判据是能完成同一任务,不是复现同一动作(对应 UI6-1)。 |
| 可选 | 放弃操纵的方式 | abort.methods | 非空集合:取消键、放回原处、非法区域释放、显式取消控件。区分用户取消与系统中断;取消清除本次预览,不覆盖无关并发变化。具体生效边界由 commit.policy 决定。 | 提供任何连续操纵时配置,不因没有拖放而不适用(UI6-5)。 |
| 可选 | 操纵撤销分组 | undo.unit | 引用:与 reversibility.undo.granularity 相同的分组策略。一次完整操纵及其派生变更为一步;不能覆盖其他有效编辑。 | 提供操纵且承诺撤销时配置(UI6-4)。 |
| 可选 | 精度等价输入 | precision.alternative | 集合:步进键、数值输入、对齐与吸附、放大后操纵、按对象选择目标。需要精细定位或小幅调整的操纵不得为空集合。 | 操纵结果对位置、大小或顺序敏感时配置;精度要求不得由用户的手部稳定程度承担(对应 UI6-6)。 |
| 可选 | 操纵生效边界 | commit.policy | 映射:操纵类型→预览后一次提交/持续生效且可结束或补偿。附生效条件、中断处置、取消范围与补偿依据。未知结果不能称已恢复。 | 提供拖动、缩放、框选、连续调整等任一操纵时配置(UI6-5)。 |
边界:直接操纵是输入方式,不是功能本身。drag.mode 与 drag.alternative 描述的是同一个功能的两条通道,不是两个功能——等价路径缺失时,这项功能对不使用指点设备或难以完成拖动动作的用户就等于没有。预览管"放下之前知道什么",cross_container.semantics 管"放下之后原处还剩什么",abort.methods 管"不放下会怎样",三者须分别成立。
八、可选项的联动要求
能力可以不提供;提供后,依赖必须完整。下表不新增字段或第三种级别,相关值可由产品规则或设计系统预设继承。表内省略共同前缀 gui.。
"未满足时"一列的统一读法:依赖未满足的配置判为无效——新操作不得以该能力承诺开放;已经存在的选区、草稿、在途操作,以及仍在期限内的撤销能力,按其原有的有效契约保留,不因配置缺项被回收。降级须提供经核实的等价路径,不得以确认、同步等待或"已告知"替代被缺失依赖所支撑的义务。
| 能力或承诺 | 必须明确的依赖 | 未满足时 |
|---|---|---|
| 提供多选 | selection.model 为多选档时须有 visibility、persistence.on_view_change、actions.scope;存在跨页选择时须有 include_filtered。 | 只提供单选;命令作用于当前单个对象,不因存在高亮而扩大作用范围。 |
| 提供批量操作 | selection.limit、object.action.scope.display、feedback.batch.result.granularity 解析为逐对象结果契约、failure.content。 | 逐个执行;不提供"对全部结果一次性执行"的入口。 |
| 提供撤销 | reversibility.undo.mode 非"不提供"时须有 undo.scope、undo.granularity;须有 undo.ttl;可能失败时须有 undo.failure.mode,存在并发修改时须有 feedback.concurrency.policy。 | 该配置无效:新操作不得以"可撤销"承诺开放,须按 UI2-4 重新裁决其确认档位并记录;已发生且仍在期限内的撤销能力照常可用。确认不替代技术上已具备的撤销能力——技术上可撤销而不提供撤销,仍须按 UI2-2 逐类记录理由与后果评估。 |
| 执行不可逆操作 | reversibility.irreversible.actions 已列出该操作;confirm.level 与其后果相称;object.action.scope.display 可解析到受影响对象。 | 不提供该操作,或改为可撤销的实现(先标记后清理)。 |
| 使用乐观更新 | feedback.optimistic.mode 为“开启且失败时回滚并告知”;concurrency.policy、回滚范围和 failure.content 齐备,未知先核对。 | 关闭乐观更新;确认之后再呈现结果。 |
| 操作可能耗时超出等待预期 | feedback.progress.info 已明确能否取消与是否阻塞;states 的阶段与结果维度齐备。 | 该配置无效:不新增该长耗时路径。即时受理反馈与真实的等待状态仍须呈现——同步执行不自动产生受理反馈;进度未知时明示"剩余量未知",不以动画伪造进度,也不以"完成前不呈现结果"代替受理告知。 |
| 使用自动消失的提示 | feedback.notice.duration 已测定并记录依据;撤销、重试与详情入口不随其消失。 | 使用不自动消失的呈现;由用户关闭。 |
| 声明支持某种输入方式 | 该方式在 input.methods 中;完整支持覆盖全部 core_tasks,限定支持列明子集和 capability.gaps,两者不混称。 | 不列入 methods;在能力说明中写明该方式不受支持及其影响。 |
| 提供上下文菜单或悬停内容 | input.hover.role 与 context_menu.role 均非"唯一入口"档;常驻等价入口可解析。 | 把入口移到常驻位置;上下文菜单仅作快捷方式。 |
| 保存草稿 | entry.draft.mode 的持久化位置集合非空时须有 draft.ttl;save.semantics 可解析到该草稿对应的事实组合。 | 不保存草稿,并在用户开始投入之前说明。同一会话内不因系统一侧的行为丢失已输入内容,这一项不随草稿策略关闭而解除(见 UI5-1)。 |
| 提供表单校验 | entry.validation.timing、error.placement、error.content 三项齐备。 | 仅在提交时校验,并给出可定位到字段的错误说明。 |
| 提交可能失败 | entry.submit.failure.retain 为保留档;feedback.failure.content 含可执行的下一步与重试是否安全。 | 不提供该提交路径;先保留本地输入并限制提交,补齐依赖后再开放;异步提交仍须满足同样依赖。 |
| 拦截应用自身可控制的导航 | entry.leave.guard 的判定条件可解析到实质变更;保存、放弃、取消三个选项可分别执行。 | 补齐离开判据,或在持久化已被验证后采用自动草稿;不能以取消拦截直接丢弃输入。 |
| 离开由运行环境控制(关闭标签页、系统级返回) | entry.leave.guard 已声明该环境实际支持的提示能力与其限制;草稿策略独立承接内容。 | 不依赖该提示;不得声称提供了环境不支持的三选项。提示至多提醒一次,不作为持久化机制。 |
| 提供拖放 | manipulation.drag.mode 为“提供且存在非拖放的等价路径”时须有 drag.alternative(含至少一条单指针、不拖动路径)、drop.preview、abort.methods、commit.policy;存在跨容器投放时须有 cross_container.semantics。 | 不提供拖放;用菜单、剪贴或目标选择完成同一任务。 |
| 操纵结果对精度敏感 | manipulation.precision.alternative 非空;承诺撤销时 undo.unit 解析到一次完整操纵分组。 | 不提供该操纵;改为数值或序号输入。 |
| 对象可能不可用或受限 | object.unavailable.mode、restriction.kind、unavailable.reason.source 可解析且与实际拦截判定一致。 | 不显示该对象;不呈现无法解释的不可用状态。 |
| 同一设备上多种输入并存 | input.switch.preserved 的五项固定保护项齐备;selection.persistence.on_view_change 覆盖切换引起的视图变化。 | 该配置无效:不得声明支持多种输入方式并存。"切换时告知状态已重置"不是合格回落——告知不抵消 UI4-3 对重置的禁止;已存在的选区与草稿仍须保留。 |
| 远端写入与安全重试 | feedback.states、unknown.action、retry.policy(允许重试时),去重与核对机制可用。 | 不自动重发,保留记录与核对入口;只限制相关写入。 |
| 文本录入与动态校验 | entry.input.policy、validation.timing,组合输入与异步结果绑定可验证。 | 保留输入,暂停会破坏组合输入的校验或格式化,不关闭基础输入。 |
| 动态界面和状态消息 | input.focus.policy、keyboard.policy、feedback.announcement.policy。 | 使用已验证的原生控件或静态等价路径,不能只隐藏焦点问题。 |
| 解释指针及连续动作 | input.pointer.policy;连续操纵还需 manipulation.commit.policy、abort.methods。 | 不启用未验证的自定义动作,保留同任务的可访问命令入口。 |
"继承默认"必须能解析到明确的值、来源与依据,不能只是一句说明。
九、配置决定与生效
每项实际配置记录:最终值、适用范围、决定方、理由、依据、依赖与生效条件。产品预设可以按对象类型、操作类别和场景细化;组织限制只能收紧,用户偏好只调整允许的范围,不能关闭固定底线。
新决定默认作用于新操作;已经存在的选区、草稿、在途请求、撤销窗口按其已承诺条件处理。限制收紧时拦截尚未提交的受影响动作,保留已发生事实和核对入口。禁止借重新解析配置清空工作状态、缩短既有恢复窗口,或把未知结果改成未提交。
冲突与缺项必须指明字段、适用条件、冲突来源和受影响能力。一个功能配置无效,只限制依赖它的新操作;不影响独立的有效能力。
十、固定底线:不能通过配置关闭
对象与选区。可操作的对象与不可操作的对象可区分,且这种区分不只由悬停或试探提供。不可用状态说明原因与恢复条件,呈现给用户的原因与实际执行拦截的判定来自同一处。一次操作的作用对象在提交前可解析;作用于多个对象且含不可逆后果时,数量与具体对象(清单或可核对的查询范围)在提交前均可获知,范围口径(仅当前页/当前筛选结果全部/显式选定且跨筛选)与其快照或动态查询性质被说明;确认之后执行范围不无声扩大。选区由用户的指定建立,不由滚动、悬停或未声明为选择动作的点击推定。当前选中了什么可见;选区可能超出可视范围时提供计数或清单。排序、筛选、分页与刷新之后,选区按对象身份保持或明确清空并告知,不静默改变其所指的对象。为单个对象设计的命令不因存在选区而扩大作用范围。
后果与可逆。操作的影响范围与是否可逆,在确认点之前可知,不在结果出来之后解释。低后果、恢复可靠且成本可接受的操作以撤销替代重复确认,不为其叠加无收益的确认;确认档位由后果、授权需求与恢复能力共同裁决,不由可逆性单独取消;不可逆的操作不以增加弹窗数量替代可逆性。撤销的作用域与粒度可解析,一次用户可识别的操作对应一步撤销,内部事务的多步不暴露为多次必要撤销;一次完整操纵及其派生变更一并撤销。撤销失败或部分失败时如实说明未撤销的部分并给出补救路径,不呈现"已撤销"。破坏性动作不设默认执行的默认值。已经外发的副作用不因界面上的回退而被称为已收回。
反馈与状态。操作阶段(本地接收/排队/执行中/结束/未知)与操作结果(待定/成功/失败/部分成功/已取消/未知)分别表达、各自可分辨,不合并为一种呈现;结果取不到依据时保留"未知"并提供核对路径,不改写为失败或尚未提交,也不据此自动重发。界面上的即时变化不作为服务端已接受的证明;先呈现后确认的更新在失败时回滚并告知,不静默回滚。批量操作逐对象报告结果,不以整体结论掩盖部分失败。失败信息包含受影响对象、原因与可执行的下一步。无法给出进度时如实呈现未知,不以动画伪造进度。撤销、重试与详情入口不随自动消失的提示一同消失,提示的存续时间不构成用户的操作期限。
输入与录入。完整支持的输入方式能完成全部核心任务;限定支持列明任务子集与替代路径,不能借此豁免适用的键盘与拖动替代要求。完成任务所必需的信息与操作不只在悬停或上下文菜单中存在。同一设备上切换输入方式不重置选区、草稿、滚动位置、展开折叠状态与进行中的操作,"已告知重置"不构成满足。由产品自身实现的拖动功能,除键盘路径外另有不要求拖动、不依赖路径手势的单指针路径,两者分别成立。校验不在用户尚未写完时判错;错误可定位到具体字段并说明如何改对。提交失败不清空已输入的内容。每一处"已保存""已同步""已完成"文案解析到一组明确的事实条件(存储位置、本地与远端持久化是否确认、业务提交结果、对外效果证据),自动保存不表述为业务已完成。离开确认只在存在实质未保存变更时出现,并让"放弃"会丢失什么可见;应用可控制的导航提供保存、放弃、取消三个选项,由运行环境控制的离开只承诺该环境实际支持的提示,且提示不作为持久化机制。同一会话内不因系统一侧的行为丢失已输入内容,这一项不随草稿策略关闭而解除。
可访问输入。控件名称、角色与状态可被辅助技术获取,焦点可见、可进入退出,模态关闭有明确返回位置;指针取消不提交,组合输入不误触提交,粘贴与自动填充默认可用。上述行为不提供关闭开关。
直接操纵。拖放不作为任何功能的唯一通道;等价路径以完成同一任务为判据,不以复现同一动作为判据。松手之前,合法目标、非法目标与放下之后会发生什么可见。跨容器的移动或复制语义在松手之前可见。预览取消不留下本次操作的部分结果,不覆盖无关的并发变化;持续生效控件明确结束与补偿边界。需要精细定位的操纵提供不依赖手部稳定程度的等价输入。一次完整操纵作为一步被撤销。
以上字段依赖与固定底线按设计规范的适用条件解释;配置审查不等于产品已经通过键盘、读屏、故障恢复或任务测试。
十一、事实映射与场景预设示例
事实契约:不是可删减的状态开关
以下是运行记录的最小逻辑字段,不计入 Token 数量:对象身份、操作身份、冻结的作用范围、当前阶段、结果、证据来源、内容标识、逐项结果和恢复入口。实现可合并存储,但界面判断必须能取得这些事实。
| 情形 | 阶段/结果 | 用户呈现 | 允许的下一步 |
|---|---|---|---|
| 仅本机收到输入 | 本地接收/待定 | 正在提交 | 等待,不冒充服务端受理 |
| 服务端确认排队 | 排队/待定 | 已排队 | 按真实能力取消或继续等待 |
| 接口响应丢失,远端可能已写入 | 未知/未知 | 结果待核对 | 按原操作身份查询;无防重依据不重发 |
| 一批对象分别成功、失败或未知 | 已核实结束的项分别结算,其余待核对 | 分组汇总,可逐项核对 | 重试已核实失败项,核对未知项 |
| 取消已生效且没有任何对象完成 | 结束/已取消 | 已取消,未产生更改 | 可重新发起新操作 |
| 取消时已有部分对象完成 | 结束/部分成功,记录取消原因 | 已停止后续处理,列出已完成项 | 撤销或补救已生效部分 |
“已结束/未知”也可能成立,例如已确认进程结束却丢失业务回执。映射须按事实组合定义,不能强制所有阶段机械走完。保存事实同样独立:本机与远端持久化分别取已确认/待定/失败/未知/不适用,业务提交结果沿用上述结果词表;只有相应内容的持久化回执才能支持“已保存”。
场景:看板批量归档
这是一个具体方案,非通用默认。前提:归档可恢复,不发送外部通知;服务端支持按操作身份核对逐项结果;以下策略引用均为本例定义的逻辑契约,落地时须绑定实际实现。
| 契约名 | 在本例中的确切含义 |
|---|---|
| 卡片身份 | 服务端稳定卡片 ID,排序后不变 |
| 选择快照 | 提交时冻结用户勾选 ID,筛选外保留已选,新增匹配对象不自动加入 |
| 归档分组 | 一次提交的卡片归档及计数变化为一步;只撤销该次实际成功项 |
| 核对与防重 | 重复请求复用原操作身份;服务端在操作记录保留期间去重,超期先查询对象实际状态 |
| 冲突恢复 | 保留后续编辑;无法安全撤回则停止该项并显示冲突 |
| 决定 | Token 与本例取值 | 成立条件 |
|---|---|---|
| 对象与批量范围 | gui.object.identity.key=卡片身份;gui.selection.model=多选;visibility=标记、计数与可展开清单;include_filtered=用户显式选定且跨筛选;limit=无额外上限;actions.scope=归档;persistence.on_view_change=按身份保持并呈现范围变化 | gui.object.action.scope.display 提供数量、选择快照说明与核对清单;实际批量容量已测定 |
| 可操作与限制 | gui.object.affordance.cues=文案、形状与边界;unavailable.mode=显示原因与恢复条件;原因来源与限制类型映射到实际权限和卡片状态 | 禁用原因与拦截同源 |
| 撤销与确认 | gui.reversibility.undo.mode=提供且作用于声明的作用域;undo.scope=当前看板、会话内;undo.granularity=归档分组;undo.ttl=会话结束事件;confirm.level=不确认;irreversible.actions=空集合 | 服务端恢复能力覆盖会话;退出前说明恢复边界;undo.failure.mode 含未恢复对象、补救、核对记录和残余影响 |
| 事实反馈 | gui.feedback.states=上述事实映射;ack.mode=原位状态变化加文案;optimistic.mode=关闭;placement=两者兼有 | 结果确认前显示正在归档;逐项结果映射、失败信息与核对路径齐备 |
| 失败与未知 | gui.feedback.unknown.action=提供核对路径、暂停相关提交;retry.policy=核对与防重,自动重试次数 0(表示仅在用户发起且安全条件成立时重试);concurrency.policy=暂停冲突项待用户决定 | 手动重试仅覆盖核实失败项,不新建身份重复外发 |
| 等待与通知 | gui.feedback.progress.info=能否取消、阻塞范围、剩余量未知;notice.duration=不自动消失;announcement.policy=普通状态合并播报、失败结果保留详情 | 后端未提供取消时明确不可取消;等待不阻塞无关卡片编辑 |
| 输入与焦点 | gui.input.methods=键盘、鼠标、触屏均完整支持;core_tasks=选择、归档、核对、恢复、退出;hover.role=无信息;context_menu.role=快捷入口且有等价入口 | target_size.ref 采用已测量的 Web 靶区契约;pointer.policy=释放激活;keyboard.policy 含遍历、选择与确认;focus.policy 删除行后到下一项、对话关闭返回触发者;switch.preserved 保留全部固定项;capability.gaps 有测试支持的空集合 |
| 拖放加速 | gui.manipulation.drag.mode=提供且存在非拖放的等价路径;cross_container.semantics=移动;commit.policy=预览后一次提交;undo.unit=归档分组 | drop.preview 含目标有效性、目标列和结果位置;drag.alternative=键盘及点按“移动到”菜单;abort.methods=取消键、非法区域释放 |
| 不适用 | 草稿、校验与文本输入相关字段、gui.manipulation.precision.alternative;gui.entry.save.semantics 使用业务提交结果映射 | 本例是归档流程,不含文本录入;不要求精确坐标。gui.selection.focus.coupling=选择与焦点分离;不可把整个看板编辑功能一并排除 |
评审时逐项删除必要依赖,预期是对应新能力配置无效,同时已有选择、在途结果、草稿和撤销承诺保留。再走一次无故障路径:没有额外审批或重复确认,键盘与点按均能完成归档。这两个方向共同检验“有保护”与“能顺畅工作”。
配置交付与校验
选择模型不表示当次选区。键盘、点按和拖放引用同一稳定对象身份与操作合同;排序、筛选或分页后按身份核对,不把原行号再次解析为对象。示例仅检验选择模型取值,不证明选区与撤销机制已实现。
随附的可执行样例只覆盖 gui.selection.model,其余字段按本字典逐项校验;未覆盖不等于不适用或已通过。样例是所选字段的格式正反例,不是可直接启用全部能力的产品预设。完整产品交付另外包含适用性、依赖、证据、执行映射及进行中操作的生效边界。
字段名、类型或含义变更时更新引用方与验收样例;仅修改说明且不改变合法行为的,保留已有字段名。调用方读取解析后的有效配置,不由 UI 控件、动画或模型文字反推权限、测量或完成事实。参见对应场景。
参考来源
本文件支撑设计规范和Design Token。来源用于核对具体事实、机制与适用边界;本规范中的设计取舍不因引用来源就成为外部标准的原文要求。
一、证据的读法
| 类型 | 能支持什么 | 不能推出什么 |
|---|---|---|
| 成文标准 | 其适用对象、等级和例外内的要求 | 单条通过不代表整个产品符合标准 |
| 标准说明与交互模式 | 条款意图、例子和可行的控件行为 | Understanding 和 APG 不是额外的符合性条款 |
| 作者研究与设计主张 | 用户问题、概念模型、设计方向 | 经典论述、小样本研究不证明所有产品都应采用同一方案 |
| 平台与工程文档 | 平台惯例、事件模型及恢复机制 | API 存在不证明产品已实现,也不证明用户能正确理解 |
| 本规范推导 | 将对象、输入、恢复等承诺转为可验收要求 | 不冒充来源中的实验结论或强制规定 |
“本次核验”指实际读取相关章节,不表示全文系统综述、运行代码或实机测试。“保留资料”沿用已有来源入口与证据限制,本次未重新验证全文;不将其标记为本次实测。文献出版年份、标准名称及条款号用于准确定位来源,不是本规范的发布记录。
二、经典论述与设计依据
| 编号 | 来源 | 支持位置与边界 | 核验范围 |
|---|---|---|---|
| R01 | Shneiderman,Direct Manipulation | 对象持续呈现、增量可逆操作与即时可见结果支撑 UI1、UI2、UI6;直接操作不自动等于易用。理论与经验论述,不提供通用时间或尺寸阈值。 | 保留作者大学公开副本;历史理论资料 |
| R02 | Shneiderman,Eight Golden Rules | 反馈、防错、撤销与控制的设计方向。不能据此断言可逆操作一律禁止确认。 | 保留作者公开主张 |
| R03 | Hutchins、Hollan、Norman,Direct Manipulation Interfaces | 执行与评价的距离支撑对象、后果、反馈的可理解性;没有通用数值或跨产品效果证明。 | 保留大学课程公开副本;历史理论资料 |
| R04 | Nielsen,Usability Heuristics、Error Message Guidelines | 系统状态、用户控制、错误预防与可恢复信息支撑 UI1—UI5。启发式检查不能替代用户测试。 | 保留作者机构资料 |
| R05 | Nielsen,Response Times | 反馈与等待的感知量级参考;不将经典量级直接写成所有场景的硬门槛。 | 保留历史实践资料 |
| R06 | Abowd、Dix,Giving undo attention;Cass 等,An Empirical Evaluation of Undo Mechanisms | 支撑从用户理解的动作定义撤销。前者仅有前言与摘要;后者为 28 人、单院校、纸面任务研究,不能推断通用最优撤销模型。 | 保留既有阅读范围与局限 |
三、输入、可访问性与运行环境
| 编号 | 官方来源 | 支持位置与边界 | 核验范围 |
|---|---|---|---|
| R07 | W3C WCAG;拖动动作说明;目标尺寸说明;错误预防说明 | UI6-1:单指针不拖动替代与键盘可操作分别验证,保留必需和未修改用户代理行为的例外。UI4-4:2.5.8 的 24×24 CSS px 下限有间距、等价、行内、用户代理控制与必需例外,不与 pt、dp 换算。3.3.4 在适用情形要求可逆、检查、确认至少一项,不建立“撤销优于确认”的普遍结论。 | 本次读取拖动与尺寸说明及其中准则文本;错误预防保留已有阅读范围,不宣称重读主标准全文 |
| R08 | W3C APG Dialog Modal;Grid | UI4-6:模态内部遍历、关闭与焦点返回,触发者消失时选择有意义的后续位置;复合控件区分焦点与选择。APG 为实现指引,不是符合性标准。 | 本次读取模态模式;网格为保留资料 |
| R09 | WHATWG HTML:beforeunload;MDN beforeunload | UI5-5:环境控制的离开提示有触发、文案与可靠性限制,不能承诺应用内三按钮能力,也不能作为持久化机制。 | 保留资料;HTML 原文相关算法此前未完整取得,平台解释仅作实现参考,本次未复核 |
| R17 | W3C Pointer Cancellation | UI4-7:区分按下、释放、取消与反转,按下触发必需时有例外。普通按钮释放激活有助于移出取消;不要求每次操作增加确认。 | 本次读取准则、意图、例子和例外 |
| R18 | W3C UI Events:Composition Events | UI5-7:组合输入具有开始、更新、结束及组合状态;按键事件仍可能同时产生。防止选词误提交是本规范从输入完整性推导的产品要求,不保证所有浏览器事件顺序完全一致,须实机验证。 | 本次读取组合事件与 isComposing 相关章节 |
| R19 | W3C Redundant Entry;Accessible Authentication | UI5-7:同一流程重复资料可带入或选择,保留实质、安全或信息失效例外;认证应支持可用的辅助机制,粘贴与密码管理器是相关实现方式。这不要求将凭据保存进草稿。 | 本次读取准则及意图;未进行认证符合性评估 |
| R20 | W3C Content on Hover or Focus;Focus Not Obscured;Status Messages | UI4-2:补充内容的可关闭、可移入和持续性及适用例外。UI4-6:作者内容不完全遮挡焦点。UI3-1:状态消息可由辅助技术获取而无需抢焦点;具体合并频率由任务测试决定。 | 本次读取相关准则与解释 |
对比度豁免与原因可达是两件事:禁用控件可能符合其适用标准的视觉豁免,仍须提供真实原因和恢复路径。不得把这写成平台指南与本规范的事实冲突。
四、平台与工程机制
| 编号 | 来源 | 支持位置与边界 | 核验范围 |
|---|---|---|---|
| R10 | Apple HIG Undo and redo、Drag and drop | 撤销、拖放反馈和替代入口的机制参考;不将单一平台惯例写成所有平台的统一默认。 | 保留平台资料,本次未重取客户端渲染正文 |
| R11 | Material States、Accessible structure | 区分启用、禁用、焦点、按压等表现状态;视觉状态不能替代业务事实。平台单位与推荐不能直接当作 Web 符合性阈值。 | 保留平台资料,本次未重取客户端渲染正文 |
| R12 | Microsoft Input primer、Keyboard interactions、Selection mode、Drag and drop | 多输入任务路径、选择模型、焦点与投放语义的实现参考。面向其平台生态;未讨论某一替代机制不表示反对它。 | 保留官方资料 |
| R13 | Redux Toolkit Manual Cache Updates;TanStack Optimistic Updates | UI3-4:并发乐观补丁回退可能出现竞态,可通过失效和重取可信状态恢复。保护后续编辑与向用户解释是本规范要求,库不会自动完成产品契约。 | 本次读取 Redux 的乐观更新与竞态提示;TanStack 为保留资料 |
| R14 | React useOptimistic;Apollo Optimistic mutation results | 将预测呈现与已确认状态分开;机制示例不能证明外部副作用已撤销。具体 API 行为须在采用时复核。 | 保留官方资料 |
| R15 | Baymard Inline Form Validation;NN/g Errors in Forms | 过早报错、错误定位与修正反馈的研究及实践参考;不据此给出通用防抖毫秒数。 | 保留公开文章;未取得付费研究方法,不外推到所有表单 |
| R16 | Design Tokens Community Group Format Module | 设计值、类型和别名的交换格式参考;本字典中的行为策略不是标准内置类型,不宣称直接兼容其验证器。社区报告不等于 W3C Recommendation。 | 本次读取格式结构与状态,未验证工具互操作 |
| R21 | AWS Builders' Library Making retries safe with idempotent APIs | UI3-2、UI3-5:无响应不等于未执行,重试需操作身份与防重契约。次数限制、禁用按钮或显示错误不能单独保证副作用不重复。 | 本次读取请求身份、重复执行与重试机制 |
五、从来源到可检验要求
| 设计问题 | 本规范的决定 | 对应位置 |
|---|---|---|
| 几次点击看起来正常,但实际重复写入 | 区分即时反馈与真实受理;重试保留操作身份,未知先核对 | UI3-1、UI3-2、UI3-5;feedback.retry.policy |
| “已保存”混合地点、持久化与业务生效 | 按独立事实绑定文案,并绑定具体内容 | UI5-6;entry.save.semantics |
| 失败回滚抹掉后续成功编辑 | 按贡献回退、重取合并或停在冲突,不全量覆盖 | UI2-3、UI3-4;feedback.concurrency.policy |
| 有拖动加快捷键,却不能仅点按完成 | 点按与键盘两条路径独立验证全部适用功能 | UI6-1;manipulation.drag.alternative |
| 全部控件“可聚焦”但任务走不通 | 测进入、退出、模态、删除、虚拟列表与状态播报 | UI4-6;input.focus.policy、feedback.announcement.policy |
| 中文选词回车同时提交 | 组合状态与快捷键分开,最终文本再校验 | UI5-2、UI5-7;entry.input.policy |
| 所有连续控件都被写成松手前不生效 | 区分预览提交与持续生效,取消和补偿都说清 | UI6-5;manipulation.commit.policy |
| 任一字段缺项就删除已有能力 | 限制未成立的新承诺,保留已有工作和恢复入口 | Token 联动表与生效约定 |
六、待验证的问题
- 反馈时长:没有适用于所有设备与任务的通用值。用目标人群测试首次反馈是否被发现、等待信息是否足够、提示结束后是否仍能恢复;记录分布与任务条件,不只记录平均值。
- 确认的净收益:低后果操作减少确认是设计选择;同时测误操作恢复和正常任务负担,不能拿经典启发式当对照实验。
- 批量范围理解:跨页、跨筛选与动态查询的呈现须通过用户任务验证,准确计数不保证用户理解实际范围。
- 输入与平台兼容:组合输入、虚拟列表、画布语义与模态焦点须在目标浏览器、系统和辅助技术上验证;自动扫描不能证明整条任务可完成。
- 分类与覆盖:独立评审能发现归属分歧,不能证明领域已被穷尽。真实失败、边界案例与新功能继续进入检查清单。
本次工作完成文档与来源层面的核对,没有执行产品实机测试、用户研究、系统性文献综述或完整无障碍符合性评估。