Skip to content

[app-shell] ActionParamDialog 的 boolean 分支不下发 id,于是同一个控件被两个同文本 label 引用(可访问名重复),而它自己的通用分支一直是对的 #3962

Description

@yinlianghui

#3952 时为确认「BooleanField 的 id 回退链里 config.name 一项不能删」而实测了这个对话框,顺带量到一个既有缺陷。与 #3952 同族但不同站点、不同包,所以另立单。

实测(在 #3952 修复之后、真 dialog 渲染)

controlId=confirmed  role=checkbox
labels=[
  { "text": "Confirm This", "for": "confirmed", "srOnly": true,  "resolves": true },   <- widget 自己发的
  { "text": "Confirm This", "for": "confirmed", "srOnly": false, "resolves": true }    <- dialog 发的可见 label
]

两个 label、同一段文本、同一个目标控件。按 accname 规范,引用同一控件的多个 label 元素会拼接成可访问名,所以屏幕阅读器听到的是 "Confirm This Confirm This"。for 都能解析,所以这不是 #3952 那种悬空 —— 是重复。

成因

packages/app-shell/src/views/ActionParamDialog.tsx 的 boolean 分支渲染 Label htmlFor={param.name},但给 widget 传 id

  • 通用分支(同文件,下面几十行)传的是 id={param.name}
  • boolean 分支没传,全靠 BooleanField 的 id 回退链第二项(config.nameparamToFieldname: param.name)恰好产出同一个字符串,关联才成立。

也就是说这个分支的 label 关联是隐式成立的:它依赖 widget 内部的回退实现细节,而不是自己下发 id。同时因为 widget 收不到 host id,就无从知道 host 已经渲染了 label,于是照旧发一份自己的 sr-only label —— 重复由此产生。

#3952 之前,表单渲染器那条路径上这个重复更严重:那边可见 label 指向的 id 根本不存在。这里两个 label 都指对了,所以只是名字重复,不影响点击。)

修法(#3952 落地后是一行)

boolean 分支像它自己的通用分支那样传 id={param.name}

需要补一个钉子:boolean param 的可访问名恰好等于 param label(不是它的两倍),且 getAllByLabelText 只解析出一个控件。packages/app-shell/src/views/ActionParamDialog.ariaRequired.test.tsx 已经有这个 dialog 的 boolean 分支用例,是自然的落点。

参考

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions