实施 #3299(PR #3340,给五处渲染器送 aria-required)时逐处核对发现的相邻但不同类缺陷,按范围栅栏不在该 PR 内修,单独立此单。#3299 修的是「必填状态不进 a11y 树」;本单是「label 与控件根本没有程序化关联」——即便 aria-required 已经到位,控件的可访问名仍然是错的或缺失的。
两处清单(已逐处核对)
-
packages/plugin-detail/src/InlineCreateRelated.tsx(Create 页签,~L208-L220):label 元素没有 htmlFor,对应的 Input 没有 id,两者也不是包裹关系。控件的可访问名只能退化到 placeholder("Enter name"),label 文本(真正的字段名)对屏幕阅读器不可达;点击 label 也无法聚焦输入框。
-
packages/components/src/custom/action-param-dialog.tsx(select 分支,~L171-L189):Label htmlFor={param.name},但该分支的控件是 Radix SelectTrigger,没有设置 id={param.name}——htmlFor 指向一个不存在的 id,combobox 从 label 得不到可访问名。其余分支(textarea/number/date/text)的 Input/Textarea 都设了 id={param.name},只有 select 漏了。
(同文件家族中 app-shell 的 ActionParamDialog.tsx 无此问题:paramToField 保留 name,字段 widget 用 config.name 作 id,与 htmlFor 对得上。)
建议修法
- InlineCreateRelated:label 加
htmlFor、Input 加 id(如 inline-create-${field.name},注意同页多实例时的唯一性,可结合 React.useId)。
- custom action-param-dialog:
SelectTrigger 加 id={param.name}。
验收
关联:#3299、#3290、PR #3340。
实施 #3299(PR #3340,给五处渲染器送
aria-required)时逐处核对发现的相邻但不同类缺陷,按范围栅栏不在该 PR 内修,单独立此单。#3299 修的是「必填状态不进 a11y 树」;本单是「label 与控件根本没有程序化关联」——即便aria-required已经到位,控件的可访问名仍然是错的或缺失的。两处清单(已逐处核对)
packages/plugin-detail/src/InlineCreateRelated.tsx(Create 页签,~L208-L220):label元素没有htmlFor,对应的Input没有id,两者也不是包裹关系。控件的可访问名只能退化到 placeholder("Enter name"),label 文本(真正的字段名)对屏幕阅读器不可达;点击 label 也无法聚焦输入框。packages/components/src/custom/action-param-dialog.tsx(select 分支,~L171-L189):Label htmlFor={param.name},但该分支的控件是 RadixSelectTrigger,没有设置id={param.name}——htmlFor 指向一个不存在的 id,combobox 从 label 得不到可访问名。其余分支(textarea/number/date/text)的Input/Textarea都设了id={param.name},只有 select 漏了。(同文件家族中 app-shell 的
ActionParamDialog.tsx无此问题:paramToField保留name,字段 widget 用config.name作 id,与htmlFor对得上。)建议修法
htmlFor、Input 加id(如inline-create-${field.name},注意同页多实例时的唯一性,可结合React.useId)。SelectTrigger加id={param.name}。验收
getByLabelText(字段 label)能命中控件;toHaveAccessibleName断言可访问名等于 label 文本(对象表单之外的一批渲染器仍把必填状态画成星号而不送进 a11y 树(#3290 的同类缺陷,另外五处) #3299 已把星号aria-hidden,不会混入)。关联:#3299、#3290、PR #3340。