组件状态标准
组件状态用于表达组件是否可见、可操作、被选中、获得焦点、正在加载或处于异常。状态必须具有稳定语义,不能只为某个视觉效果临时命名。
状态总表
| 状态 | 语义 | 典型视觉 | 交互要求 |
|---|---|---|---|
normal |
默认可操作。 | 默认背景、文本和边框。 | 可按组件语义响应输入。 |
hovered |
指针位于可交互区域。 | 弱背景或边框变化。 | 不改变布局,不抢焦点。 |
pressed |
指针或键盘正在激活。 | 比 hover 更明确的按下反馈。 | 操作取消、离开或禁用后恢复。 |
focused |
键盘焦点或文本输入焦点。 | focus ring、caret 或 focused border。 | 可通过键盘继续操作。 |
selected |
当前项被选中或激活。 | 比 hover 更强的选中背景或强调条。 | 必须可与 hover/focus 同时表达。 |
disabled |
整体不可交互。 | 弱化文本和背景。 | 不响应 pointer、keyboard、shortcut、popup。 |
readonly |
值可看但不可改。 | 保持可读,通常弱化编辑入口。 | 允许复制/选择由组件语义决定。 |
loading |
正在加载或处理。 | spinner、遮罩、骨架或等待状态。 | 明确是否阻断输入。 |
empty |
无数据但非错误。 | 空状态文案或占位。 | 可保留新增、刷新等操作。 |
error |
数据或操作失败。 | error 色、错误文本、错误图标。 | 不吞掉重试或修正入口。 |
warning |
有风险但仍可继续。 | warning 色或提示。 | 不默认阻断操作。 |
success |
操作成功或状态正常。 | success 色、成功图标。 | 不应长期占据主要视觉层级。 |
visible 是所有 RenderObject 的基础状态,语义见 组件基础状态契约。它不属于普通交互状态,因为它会退出布局、绘制、hit test 和焦点。
状态优先级
组件同时拥有多个状态时,按以下优先级处理:
visible=false
> disabled
> loading-blocking
> error
> pressed
> selected
> focused
> hovered
> readonly
> normal
说明:
visible=false时组件不再占据页面布局,也不响应输入或保留焦点。disabled最高,组件不再保留 hover、pressed、drag、popup 或 focus 等临时状态。- 阻断式 loading 类似 disabled,但可保留 loading 视觉。
error可以和 focused 同时存在,输入框常见做法是 error border 加 focus ring。pressed是瞬时反馈,释放后回到 selected / focused / hovered 的组合。selected不能被 hover 覆盖;hover 只能在 selected 基础上轻微增强。readonly是能力约束,不一定需要强视觉;它不能覆盖 error 或 focus。
状态组合规则
Hover
- 只在可交互命中区域内出现。
- 指针离开,或组件被隐藏、禁用时,hover 反馈必须消失。
- hover 不应改变组件尺寸、位置或周围内容的布局。
- 高密度数据行的 hover 反馈应保持轻量,不应造成整表闪烁或卡顿。
Pressed
- pressed 必须来自明确激活动作:pointer down、Space、Enter 或拖拽 handle。
- 操作取消,或组件被禁用、隐藏时,pressed 反馈必须恢复。
- pressed 反馈不改变尺寸。
- click 回调应在 release 且仍命中时触发,除非组件语义另有说明。
Focused
- 可键盘操作的组件必须能获得焦点并绘制 focus ring。
- focus ring 不占布局尺寸。
- pointer 点击是否聚焦由组件语义决定;输入框应聚焦,纯按钮可聚焦。
- 组件被禁用后不能继续持有焦点。
Selected
- selected 表示业务选择或当前激活项,不等于 focused。
- selected 项在 hover 时仍应保持 selected 主视觉。
- 多选组件必须区分 selected、active/focused item 和 anchor。
- 当前文档 tab、当前导航项、当前表格行都属于 selected 或 active 语义,但 token 可按组件类别派生。
Disabled
禁用后必须:
- 阻断 pointer、keyboard、shortcut、popup、drag。
- 从焦点顺序中移除。
- 不再保留已有焦点。
- 关闭该组件已经打开的 popup、tooltip、context menu 或 drag preview。
- 不再显示 hover、pressed 或拖拽中的临时反馈。
- 使用 disabled token 绘制。
Readonly
readonly 不等于 disabled:
- 输入类控件通常保留文本选择、复制和滚动。
- 选择类控件不打开 popup。
- 命令类控件通常不提供 readonly,应使用 disabled。
- readonly 不应让内容不可读。
Loading、Empty、Error
- loading 要说明是否阻断输入;非阻断 loading 不应禁用整个组件。
- empty 是正常状态,不应使用 error 颜色。
- error 需要给出可读错误信息或可定位的错误视觉。
- 表格、树、列表、图表等数据组件应把 loading、empty、error 放进状态层,而不是让业务页面重复绘制。