Skip to content

InlineCreateRelated 的 Link 页签搜索框只有 placeholder、没有任何 label:可访问名靠 placeholder 兜底,输入后即消失 #3381

Description

@yinlianghui

实施 #3341(PR #3380,给 Create 页签的 label 补 htmlFor/id)时,在同一文件里核对到的相邻缺陷。按 #3341 的范围栅栏(其验收只覆盖正文枚举的两处 label→control 关联)不在该 PR 内修,单独立此单。

与 #3341 不同类:#3341 是「label 存在但没和控件关联上」;本单是「根本没有 label」。

现象

packages/plugin-detail/src/InlineCreateRelated.tsx(Link Existing 页签,origin/main ~L253-L260):

{/* Link Existing Tab */}
{onLinkRecord && (
  TabsContent value="link" ...
      div className="relative"
        Search className="absolute left-2.5 ..." /
        Input
          placeholder={`Search ${objectName}…`}
          value={searchQuery}
          onChange={(e) =} handleSearchChange(e.target.value)}
          className="h-8 text-sm pl-8"
        /

(为避开 GitHub 正文的标签清洗,上面省略了尖括号。)

该 Input 既没有关联的 label 元素,也没有 aria-label / aria-labelledby;同段落里我已核对 grep -c "aria-label\|htmlFor" 在该区块为 0。它的可访问名只能落到 placeholder 上,而 placeholder 作为可访问名是 HTML-AAM 的最后兜底,存在两个实际问题:

  1. 用户一开始输入,placeholder 就消失,控件在视觉上失去任何名称提示(WCAG 对 placeholder-as-label 的经典反对理由);
  2. 兜底行为跨实现不一致 —— 这一点在 两处表单控件缺 label→control 关联:InlineCreateRelated 的 label 无 htmlFor/id,custom action-param-dialog 的 select 分支 htmlFor 指向不存在的 id #3341 的验证里实测到了:dom-accessibility-api 完全没有实现 placeholder 兜底(0.5.16 / 0.6.3 两个版本里 placeholder 出现次数均为 0),因此在 jsdom 测试环境下该控件的可访问名是空字符串。真实浏览器会兜底到 placeholder,测试环境不会。

旁证:同文件 Create 页签的字段输入框在 #3341 修复后已经是「label 文本即可访问名」,唯独这个搜索框还靠 placeholder。

建议修法

给该 Input 一个真正的可访问名,二选一(倾向前者,与本仓 Create 页签修完后的形状一致):

顺带可核对左侧的 Search 装饰图标是否需要 aria-hidden(本单未核实 lucide-react 当前版本的默认行为,不作断言)。

验收建议

  • getByLabelText / toHaveAccessibleName 能拿到与 placeholder 无关的稳定可访问名;
  • 断言在输入之后(placeholder 已消失时)可访问名依然成立 —— 这是 placeholder-as-label 与真 label 的分水岭。

关联:#3341(PR #3380)、#3299、#3290。

Activity

  1. self-assigned this
    on Aug 5, 2026
  2. yinlianghui commented on Aug 5, 2026

    @yinlianghui
    CollaboratorAuthor

    认领:objectui 分片 PM 滚动补位第 18 单
    会话:session_01GTRjn8xBqp75dk7kFupVRt
    分支:claude/issue-3381-link-search-label
    Worktree:objectui-issue-3381
    域:objectui 分片(plugin-detail)
    文件面:packages/plugin-detail/src/InlineCreateRelated.tsx + 相应测试 + .changeset/*.md(patch)。当前在飞 0。

    方向裁定(PM,否决窗口):取视觉隐藏 label + htmlFor/React.useId(与 #3341 修后 Create 页签形状一致;aria-label 方案否决 —— 可见文本与可访问名解耦易漂移)。label 文本与 placeholder 同源;i18n:既有 key 合适则消费,零新键(该 placeholder 本身是英文硬编码属另一族,不在本单展开)。验收照正文:getByLabelText/toHaveAccessibleName 稳定命中,且输入之后(placeholder 消失)断言仍成立;Search 装饰图标核 aria-hidden 现状,需要则补。


    Generated by Claude Code

  3. yinlianghui commented on Aug 5, 2026

    @yinlianghui
    CollaboratorAuthor

    PM 验收:ACCEPT → PR #3410 已转 ready + auto-merge(CI 16 项全部完成:14 绿 2 预期跳过),跟到 MERGED。

    落地内容(按裁定):sr-only label + htmlFor + useId(id 用带连字符段避开字段名撞车,含字面叫 search 的字段);label 与 placeholder 同源表达式,渲染逐字节未变、零新键;lucide 图标默认 aria-hidden 经读源核实后仍显式补上(摆脱依赖默认值)。反向验证 9/9 红且 Received 为空串 —— 复现 issue 所述 jsdom 无 placeholder 兜底。两处诚实标注:①「图标不进 a11y 树」断言钉的是结果而非新属性(定向反验证实 lucide 默认兜住),已注明;② 首版防撞用例修前空绿(修前根本无 id),按「整条替换 fixture」重写为读真实 id 比对。顺带记录 Radix Tabs 1.1.x 由 mousedown 激活的测试坑。

    衍生分诊:#3411(同文件卡片头关闭按钮纯图标无可访问名 —— 同文件第四类 a11y 缺陷,探针实测、查重先行)已复核入队 bug + pm:queue。

    objectui 分片 PM session_01GTRjn8xBqp75dk7kFupVRt


    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