Progress 正确报出 aria-valuenow,不再恒为 indeterminate (WEB-1381)
版本: 0.9.1 · 类型: 🐛 Bug 修复
问题
Progress 视觉上填充正确,语义上却永远被当作「不确定进度」的进度条播报。无论调用方传入什么 value,元素上都是 data-state="indeterminate" 且没有 aria-valuenow,读屏用户只能听到「进度条」,听不到百分比。
根因
ui/progress.tsx 把 value 从 props 里解构出来后,只用于 Indicator 的 translateX 位移计算,从未传给 ProgressPrimitive.Root;而 {...props} 展开也补不回来,因为 value 已经被从 rest 对象里摘掉了。
Radix 的 aria-valuenow、aria-valuetext、data-state、data-value 全部由 Root 的 value 推导,value === undefined 时回落为 null,即 indeterminate。视觉之所以一直正确,恰恰是因为它独立于 Radix context 计算——这也是这个缺陷能躲过 code review 和截图验收的原因。
改动文件
packages/design/src/components/ui/progress.tsxpackages/design/src/components/Progress/__tests__/Progress.test.tsx
改动内容
progress.tsx:在原有 Indicator 位移之外,把value一并传给ProgressPrimitive.Root。Progress.test.tsx:对 0 / 42.5 / 100 断言role、aria-valuenow与aria-valuemin/aria-valuemax;另加一条用例钉住「不传value时仍保持 indeterminate」。
影响范围
| 属性 | 之前 | 之后 |
|---|---|---|
aria-valuenow | 无 | value 合法时有 |
aria-valuetext | 无 | 有(getValueLabel,默认四舍五入成百分比) |
data-state | 恒为 indeterminate | loading / complete |
data-value | 无 | 数值 |
- 视觉零变化。 Indicator 的位移从来不依赖 Radix context。
role="progressbar"不是新增的——Radix 一直都渲染它,缺的只是数值语义。- Radix 现在会校验
value,传入非数字 / NaN /< 0/> max时console.error。此时渲染结果不变(Radix 回落为 indeterminate,视觉仍由组件自身 transform 决定),因此它暴露的是调用方原有的 bug,而不是引入新问题。 - 若有选择器依赖
data-state="indeterminate",注意它现在只对不传value的进度条生效。
配套:给进度条起名字
使用方这一侧有两件事建议同时做:
- 给进度条加
aria-label。没有可访问名称的progressbar会被念成一个匿名进度条。 - 若进度条旁边展示的百分比不是简单的
Math.round(value),请覆盖getValueLabel。ARIA 规范里aria-valuetext优先于aria-valuenow,而 Radix 默认标签走四舍五入——所以界面上向下取整显示66%的进度条,默认会被读成67%。