#5659·base-ui

当优先级为"高"时,Toast.Root 会为可聚焦元素设置 aria-hidden 属性

作者: cabuentello-source创建于 2026年9月10日更新于 2026年9月14日
标签status: waiting for maintainercomponent: toast

基础 UI 版本: 1.8.0 React 19, Next.js 16.3.4 使用 `priority: "high"` 创建的弹出消息在可访问性树中隐藏, axe 将其报告为严重级别的 `aria-hidden-focus`。键盘用户可以通过 Tab 进入弹出消息,屏幕阅读器将不会描述他们所进入的内容。 `Toast.Root` 本身在 `toast/root/ToastRoot.js` 中提供了这两个属性: - 第 423 行将 `role` 设置为 `alertdialog`,当弹出消息具有高优先级时,否则为 `dialog`。 - 第 424 行无条件地设置 `tabIndex: 0`。 - 第 428 行在弹出消息具有高优先级且视口没有聚焦时将 `aria-hidden` 设置为 `true`。因此,这种组合仅在高优先级弹出消息中出现,并且只有在视口没有聚焦时才如此。 ### 重现 无聚焦状态很重要,因此需要在一开始就说明。如果聚焦视口, `aria-hidden` 将被移除,违规将消失。需要测试的状态是普通状态,即弹出消息已出现,但尚未有人使用 Tab 进入它。 1. 在标准布局中渲染 `Toast.Provider`,`Toast.Portal` 和 `Toast.Viewport`, 将弹出消息映射到 `Toast.Root`。 2. 添加具有 `priority: "high"` 的弹出消息。 3. 不要聚焦视口。 4. 检查渲染的 `Toast.Root`。它同时携带 `role="alertdialog"`,`tabIndex="0"` 和 `aria-hidden="true"`。 5. 使用 axe 对页面进行检查。它报告了 `aria-hidden-focus`。 ### 我们期望的结果 键盘可访问的元素不应从辅助技术中隐藏。要么元素在可以聚焦时被暴露,要么在隐藏时不具备聚焦能力。 ### 可能节省您时间的一些注意事项 消息本身仍然被宣布。基础 UI 会渲染携带弹出消息文本的兄弟活动区域,因此这是一个漂浮的 Tab 停止点,而不是无声错误。这限制了其严重程度,并且这就是我们报告它而不是使用更旧版本的原因。它不是进入动画期间的临时状态。属性在 1.5 秒后仍然存在。 向 `Toast.Root` 传递 `tabIndex={-1}` 没有帮助,因为 `Toast.Root` 会自行设置该属性。这也是 Radix 中相同缺陷的文档工作绕过方法(`radix-ui/primitives#2584`),并且不适用于此处。 ### 值得标记的一个后果 对于其他用户来说 由于根元素在未聚焦时具有 `aria-hidden` 属性,Playwright 和 Testing Library 中的 `getByRole` 无法看到高优先级弹出消息。两者都解析对应于可访问性树。以 `getByRole("alertdialog")` 编写的任何测试都将以与测试行为无关的原因失败。通过 CSS 或文本来处理弹出消息是可行的。在了解原因之前,我们为此浪费了时间,因此在发生根本问题时,这可能值得在文档中加一行。 ### 相关问题 这看起来与 #5528 (下拉菜单) 和 #4678 (对话框) 相同,两者都是打开的,两者都具有 `aria-hidden` 并应用于保留在 Tab 顺序中的内容。单独提交,因为它们与 #5528 和 #4678 相同,但 #5528 和 #4678 都具有 `aria-hidden` 属性,而 #5528 和 #4678 都具有 `aria-hidden` 属性。