R1.03.5overlapping state priority设计
状态可叠加,组合态需要优先级规则
别名: 状态叠加 · 组合态 · state precedence · 优先级规则
概念解释
加载、禁用、错误、选中、焦点可以同时为真:请求还在飞,字段已被业务禁用,本地校验也没过。这时不是再画一张「加载且禁用且错误」的独立格子,而是要一条叠加优先级(overlapping state priority):哪一层准许露出来、哪一层被压住、辅助技术读哪一个。
没有这条规则,CSS 特异度或 JSX 里的书写顺序会悄悄当裁判。组合态是叠加运算,不是把笛卡尔积再画一遍。
机制
状态不是互斥枚举。交互通道、异步请求和校验器各自独立置位,真值会相交。视觉层若按「最后一个匹配的类赢」来画,同一组件在不同文件里类名顺序不同,赢家就不同:有的显示转圈盖住红字,有的红字盖住转圈还接收点击。行为层同样需要赢家:禁用为真时是否仍允许取消请求,错误为真时焦点环还在不在。
优先级是有序列表,不是新矩阵。常见顺序会把「不可用」放在可反馈的交互之上(禁用压住悬停),把「进行中」压住可提交,把「失败」压住空,但具体产品可以不同——必须写下来。未写出的优先级会在每次重构类名时改判,缺陷表现为「偶尔看起来不对」,而不是某张缺失的设计帧。
边界
互斥建模且由单一状态机保证不同时为真的控件(步进器的「当前步」),不需要叠加规则,硬加会暗示非法组合存在。全页阻塞蒙层盖住底下所有控件时,优先级在页面层已经裁定,组件内部不必再叠一层「全局忙」。打印和静态导出没有运行时相交,按最终快照出一张即可。动画插值若把两个状态画成中间色,那是过渡,不是第三条稳定的组合态,不要写进优先级表。
怎么落地
- 列出允许同时为真的状态,写成从高到低的优先级,并注明每一层压住的是外观、交互,还是两者。
- 在 Storybook 里用开关同时打开最高频的两两组合(加载+禁用、错误+焦点、选中+禁用),对照优先级表看赢家。
- 把赢家同时暴露给辅助技术:读出的名称不得和视觉赢家打架(转圈时还在说「编辑」)。
- 验证:对每个允许的两两组合截图并录一次键盘操作。视觉赢家、是否可激活、读屏播报三者必须指向同一层。任何一处不一致,就是特异度在代替优先级。