跳到主要内容

Progress 正确报出 aria-valuenow,不再恒为 indeterminate (WEB-1381)

版本: 0.9.1 · 类型: 🐛 Bug 修复

WEB-1381

问题​

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.tsx
  • packages/design/src/components/Progress/__tests__/Progress.test.tsx

改动内容​

  1. progress.tsx:在原有 Indicator 位移之外,把 value 一并传给 ProgressPrimitive.Root。
  2. Progress.test.tsx:对 0 / 42.5 / 100 断言 role、aria-valuenow 与 aria-valuemin / aria-valuemax;另加一条用例钉住「不传 value 时仍保持 indeterminate」。

影响范围​

属性之前之后
aria-valuenow无value 合法时有
aria-valuetext无有(getValueLabel,默认四舍五入成百分比)
data-state恒为 indeterminateloading / 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%。