在 #3990(PR #4002)的逐 widget 实测中量到的另一条,与那个 PR 无关也不由它引入,而是同一族的另一半:名(aria-labelledby)已在 #4002 里接上,描述(aria-describedby)在只读态仍然是「发了 id 没人引用」。单独立单。
Blocked-by: #3990(PR #4002)—— 见下「为什么现在才好修」。
实测
一次性 probe(未提交),真 form renderer + 裸注册 labelling: 'group',字段带 description: 'Some help',数「引用 …-form-item-description 这个 id 的元素个数」:
checkboxes editable descEl=SET describedbyConsumers=1 consumerTags=[div[group]]
checkboxes readonly descEl=SET describedbyConsumers=0 consumerTags=[]
radio editable descEl=SET describedbyConsumers=1 consumerTags=[div[radiogroup]]
radio readonly descEl=SET describedbyConsumers=0 consumerTags=[]
address editable descEl=SET describedbyConsumers=1 consumerTags=[input]
address readonly descEl=SET describedbyConsumers=0 consumerTags=[]
即:FormDescription 元素照常渲染、照常带 id(descEl=SET),可编辑态有 1 个消费者,只读态 0 个。可见的帮助文本在只读态与它描述的那个字段之间没有任何程序化关联。
机理
FormControl 是 Radix Slot,把 id / aria-describedby / aria-invalid 递给它包的那个 child(packages/components/src/ui/form.tsx:118-127)。
为什么现在才好修(不是当时该顺手做的)
#4002 之前只读面根本没有一个可承载的 role:role-less 的 div / span 上 aria-describedby 与 aria-labelledby 一样是空转。#4002 之后只读面有了 role="group",而 group 是一个合法的描述承载者 —— 辅助技术进入一个 group 时会宣读它的名与描述,不需要里面有可聚焦控件。所以「只读面该不该带 aria-describedby」这个问题现在才有一个明确的、能落地的答案,而当时按 #3990 的范围(把「名」接上)刻意留窄是对的。
未实测(不要按本单推断)
处置方向(未裁决)
参考
在 #3990(PR #4002)的逐 widget 实测中量到的另一条,与那个 PR 无关也不由它引入,而是同一族的另一半:名(
aria-labelledby)已在 #4002 里接上,描述(aria-describedby)在只读态仍然是「发了 id 没人引用」。单独立单。Blocked-by: #3990(PR #4002)—— 见下「为什么现在才好修」。
实测
一次性 probe(未提交),真 form renderer + 裸注册
labelling: 'group',字段带description: 'Some help',数「引用…-form-item-description这个 id 的元素个数」:即:
FormDescription元素照常渲染、照常带 id(descEl=SET),可编辑态有 1 个消费者,只读态 0 个。可见的帮助文本在只读态与它描述的那个字段之间没有任何程序化关联。机理
FormControl是 Radix Slot,把id/aria-describedby/aria-invalid递给它包的那个 child(packages/components/src/ui/form.tsx:118-127)。aria-describedby随之落地(29 个注册 field widget 在校验失败后从不携带aria-invalid—— #3306 全注册表守卫实测的账本 #3318 的既定分工);id+aria-labelledby)+role="group",刻意没带aria-describedby—— 当时的理由写在packages/fields/src/widgets/toHostGroupProps.ts的注释里:只读面没有可聚焦控件,而aria-describedby是「焦点落到可聚焦元素上时宣读」的通道。为什么现在才好修(不是当时该顺手做的)
#4002 之前只读面根本没有一个可承载的 role:role-less 的 div / span 上
aria-describedby与aria-labelledby一样是空转。#4002 之后只读面有了role="group",而 group 是一个合法的描述承载者 —— 辅助技术进入一个 group 时会宣读它的名与描述,不需要里面有可聚焦控件。所以「只读面该不该带aria-describedby」这个问题现在才有一个明确的、能落地的答案,而当时按 #3990 的范围(把「名」接上)刻意留窄是对的。未实测(不要按本单推断)
checkboxes/radio/address三类;另外四类(multiselect/rating/file/geolocation)的只读面形态各异,应比照 [fields] 只读 / 零选项的 group-labelled 选项 widget 提前 return,groupDomProps没被展开 —— host label 的 IDREF 没有消费者,标签仍然什么都不命名(#3961 的残留,checkboxes 今天的 main 上就这样) #3990 逐个量;type: 'text'的字段容器里根本没有 input 元素),已作废,不作为本单证据。谁接这条请自己量。处置方向(未裁决)
aria-describedby(它已经有role="group"这个承载者),toHostGroupProps从两键扩到三键 —— 但要一并想清楚aria-invalid/aria-required在只读面的去留,别把「控件通道」整份铺回一个非控件表面(那正是 字段 widget 把渲染器专用 props 原样展开到 DOM——schema="[object Object]"出现在真实输入框上 #3291 与 29 个注册 field widget 在校验失败后从不携带aria-invalid—— #3306 全注册表守卫实测的账本 #3318 在防的事);参考
groupDomProps没被展开 —— host label 的 IDREF 没有消费者,标签仍然什么都不命名(#3961 的残留,checkboxes 今天的 main 上就这样) #3990 / PR fix(fields): group-labelled widget 的只读/零选项分支也消费 host label 的 IDREF (#3990) #4002(只读/零选项态的 group 名接上,本条即在其验证中实测到)for悬空,checkboxes / radio / rating / file 的for落在不可 label 的 div 上 #3961 / PR fix(fields,components): 复合/分组 field widget 的组标签改用 IDREF 关联(#3961) #3978,[fields] multiselect 的 host label 也落在不可 label 的包裹 div 上 —— 与 #3961 同一失效类,但不在其审计的六个 widget 内 #3975 / PR fix(fields): name the multiselect chip group by IDREF instead of an inertfor(#3975) #3983(group 机制两次奠定)aria-invalid—— #3306 全注册表守卫实测的账本 #3318(pass-through 的分工:describedby 留在可聚焦元素上)、字段 widget 把渲染器专用 props 原样展开到 DOM——schema="[object Object]"出现在真实输入框上 #3291(白名单,不得重开 spread)