Uh oh!
There was an error while loading. Please reload this page.
fix(a11y): name InlineCreateRelated's icon-only close button (#3411) - #3413
Merged
Conversation
The card header's close button had no accessible name at all. Its only child is a lucide `X`, and lucide-react excludes childless, a11y-prop-less icons from the accessibility tree (defaulting them to `aria-hidden="true"`), so with no text, `aria-label`, `aria-labelledby` or `title` on the button the computed name was the empty string — a screen reader announced a nameless "button". Unlike #3381's placeholder case there was no browser-side fallback to soften it: empty in every implementation. WCAG 4.1.2 / 2.4.6. `aria-label="Close"` rather than #3381's visually hidden `<label>`, because this control has no visible copy for a label to stay in step with — the drift that ruling guarded against cannot arise here — and it is the shape the repo's other close buttons already use (shadcn's dialog/sheet, DashboardEditor). The icon is now explicitly `aria-hidden`, so the intent is local instead of inherited from the icon library's default. Tests locate the button structurally (the card header's only button) and then assert its name, rather than the indirect "no text-less button exists" form the issue warned about. Reverse-verified in the plain direction predicted up front: on the unfixed tree all 7 cases fail with an empty accessible name while the structural lookup still succeeds. No props, spec or visible-copy change. Refs #3411 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01GTRjn8xBqp75dk7kFupVRt
The latest updates on your projects. Learn more about Vercel for GitHub. |
Contributor
✅ Console Performance Budget
📦 Bundle Size Report
Size Limits
|
yinlianghui
marked this pull request as ready for review
August 5, 2026 22:41
Uh oh!
There was an error while loading. Please reload this page.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for freeto join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes#3411
问题
InlineCreateRelated卡片头部的关闭按钮是纯图标按钮:唯一子节点是 lucide 的X,按钮上没有文本、没有aria-label/aria-labelledby/title。而 lucide-react 会把「无 children 且无 a11y prop」的图标默认标成aria-hidden="true",把它排除出可访问性树 —— 于是这个按钮的可访问名没有任何来源,计算结果是空串,屏幕阅读器只会念出一个没有名字的 "button"。WCAG 4.1.2 / 2.4.6。与同族的 #3381 不同的是,这里连兜底都没有:占位符至少在真实浏览器里还能当最后一档名字来源,而图标按钮在任何实现下都是空串。
改动
aria-label="Close"。选aria-label而不是 InlineCreateRelated 的 Link 页签搜索框只有 placeholder、没有任何 label:可访问名靠 placeholder 兜底,输入后即消失 #3381 那种视觉隐藏 label:该按钮没有任何可见文案,InlineCreateRelated 的 Link 页签搜索框只有 placeholder、没有任何 label:可访问名靠 placeholder 兜底,输入后即消失 #3381 所防的「可见文本与可访问名解耦漂移」在这里不可能发生;而且这正是本仓其余关闭按钮已在用的形状(shadcn 的 dialog/sheet、DashboardEditor)。aria-hidden="true"。lucide 本就默认如此,写出来是让意图留在本地、不随图标库默认值变化而失效 —— 与 PR fix(a11y): 用真 label 命名 InlineCreateRelated 的 Link 页签搜索框 (#3381) #3410 给放大镜图标的处理一致。不涉及 props / spec / 可见文案变化。
测试
新增
packages/plugin-detail/src/__tests__/InlineCreateRelated.closeButtonName.test.tsx(7 例)。按 issue 的要求写成直接断言:先结构化定位该按钮(卡片头里唯一的那个 button),再断言它的名字 —— 而不是「卡片上不存在无文本按钮」这类会被其它改动带绿的间接形。覆盖getByRole('button', { name: /^Close$/ })命中、toHaveAccessibleName()非空、名字挂在真正会收起卡片的那个按钮上、图标保持 decorative、link 页签同样有名、同页两个实例各自有名。反向验证(方向在跑之前就已预判,结果一致):普通的 before-red / after-green —— 名字只有一个来源,下游也没有任何「计数型」的 gate 会反向增量。在未修的树上 7 例全红,且结构化定位本身仍然成功,说明红的是名字而不是元素挪了位:
修复后(仓根跑,以文件名确认过该文件确实进了过滤集):
消费半径已扫:
InlineCreateRelated只有具名导出、未注册进组件 registry,引用它的只有packages/plugin-detail自己的四个测试文件,无跨包 fixture 受影响。changeset:
.changeset/inline-create-related-close-button-name.md(patch)。Refs #3381(PR #3410)、#3341(PR #3380)、#3299
🤖 Generated with Claude Code
https://claude.ai/code/session_01GTRjn8xBqp75dk7kFupVRt
Generated by Claude Code