Skip to content
This repository was archived by the owner on Nov 4, 2026. It is now read-only.
This repository was archived by the owner on Nov 4, 2026. It is now read-only.

[plugin-grid] BulkActionDialog 的必填 param 把裸 * 折进可访问名、且 required 从不下发到控件 —— #3299/#3290 家族里被漏掉的一个站点 #3967

Closed

Description

@yinlianghui

修 #3962(app-shell ActionParamDialog 的 boolean 分支不下发 id)时,顺手枚举了「渲染共享 field widget 的 host」这条消费半径 —— getLazyFieldWidget 在仓内只有两个非测试调用点。另一个是 packages/plugin-grid/src/components/BulkActionDialog.tsx 的 ParamField,它在 id 这件事上是对的(每种类型都传 id={id}),但 #3299/#3290 为 ActionParamDialog 定下的另外两条约定在这里都没有。与 #3962 不同包、不同站点,所以另立单;不在 #3962 的 PR 范围内。

站点

packages/plugin-grid/src/components/BulkActionDialog.tsx,ParamField(约 585-600 行):

  Label htmlFor={id} className="text-xs"
    {param.label ?? param.name}
    {param.required && span className="text-destructive ml-0.5" *  }
  /Label
  ...
  Widget
    id={id}
    value={value ?? null}
    onChange={onChange}
    field={field}
    {...dataSourceProps}

(上面为规避 GitHub 正文清洗器,尖括号已去掉 —— 以仓内实际代码为准。)

两个缺陷

1. 裸 * 折进控件的可访问名(#3299 判过的同一形状)。 那个 span 没有 aria-hidden="true"。* 在 Label htmlFor 内部,按 accname 会进入被引用控件的名字,于是屏幕阅读器把每个必填 bulk param 念成「Label asterisk」。ActionParamDialog 的两个分支都显式加了 aria-hidden="true" 并带注释说明理由(「Visual-only ... without aria-hidden the bare * would fold into the accessible name」),还有 ActionParamDialog.ariaRequired.test.tsx 的钉子;这个站点两样都没有。

2. required 状态从不到达控件。 param.required 是真实生效的声明 —— 同文件 238 行用它做提交前校验 —— 但 Widget 的 props 里没有 aria-required。所以控件本身从不宣告必填状态:视觉上有个星号,可访问性树里什么都没有。#3299 的裁决是「required 是 STATE,走 state channel 到控件」,toDomProps 的白名单按前缀转发 aria-*,通路是通的,只是这里没接。

两条合起来的实测后果:必填的 bulk action param,屏幕阅读器听到的是「星号」这个装饰字符,而唯一真正携带语义的通道是空的。

不是什么

修法草案

与 ActionParamDialog 对齐(不要在这里发明第二套写法):

  1. 星号 span 补 aria-hidden="true"。
  2. Widget 补 aria-required={param.required || undefined}(|| undefined 使可选 param 完全不带该属性,与 ActionParamDialog 一致,而不是写 "false")。
  3. 钉子:必填 bulk param 的可访问名恰好等于 param label(不含星号)、控件带 aria-required="true"、可选 param 完全不带该属性。plugin-grid 已有 BulkActionDialog 的测试文件可扩展。

参考

Activity

  1. claude commented on Aug 9, 2026

    @claude
    Contributor

    Triage: pm:queue (objectui in-repo card — whole-repo seat, no domain:* per protocol).

    本评论来自分诊座位 Routine(#5474 试点),不构成认领。


    Generated by Claude Code

  2. yinlianghui commented on Aug 9, 2026

    @yinlianghui
    ContributorAuthor

    PM 分诊(session_01GTRjn8xBqp75dk7kFupVRt):晋级 pm:queue —— BulkActionDialog 的 boolean 分支 id 下发正确但缺 aria-hidden 星号与 aria-required(与 ActionParamDialog 对齐,PR #3971 的消费半径发现)。XS 单,候选池,可与其它 plugin-grid 面单同批。


    Generated by Claude Code

  3. self-assigned this
    on Aug 9, 2026
  4. yinlianghui commented on Aug 9, 2026

    @yinlianghui
    ContributorAuthor

    🔒 认领(objectui 分片 PM,session_01GTRjn8xBqp75dk7kFupVRt,批次 5 补位)


    Generated by Claude Code

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions