Toast viewport enters Dialog's aria-hidden subtree from react-toast 1.2.15, while staying pointer-interactive
Summary
From @radix-ui/react-toast 1.2.15, a Toast rendered while a modal Dialog is open ends up inside the dialog's aria-hidden="true" subtree. The toast remains pointer-interactive (pointer-events: auto on the toast, as shadcn/ui ships it), so an action inside it is reachable by mouse and unreachable by assistive technology at the same time.
Those two should agree. Either the toast is interactive and should stay out of the hidden subtree, or it is inert and should not accept clicks.
Versions
Bisected against a real Chromium (vitest browser mode), one variable changed per run:
@radix-ui/react-toast |
toast inside aria-hidden subtree |
|---|---|
| 1.2.14 | no |
| 1.2.15 | yes |
| 1.2.17 / 1.2.19 / 1.2.21 / 1.2.22 / 1.2.23 | yes |
Transitive changes between 1.2.14 and 1.2.15:
@radix-ui/primitive: 1.1.2 -> 1.1.3
@radix-ui/react-dismissable-layer: 1.1.10 -> 1.1.11
@radix-ui/react-presence: 1.1.4 -> 1.1.5Measured in Chromium
Same page, same components, only the toast version differing. Walking up from the action button to the root looking for aria-hidden="true", plus computed style:
1.2.14 { pointerEvents: "auto", insideAriaHidden: false }
1.2.15 { pointerEvents: "auto", insideAriaHidden: true }pointer-events is unchanged; only the accessibility tree moved.
Reproduction shape
- Render
<Toaster />(shadcn/ui's, i.e.Toast.Provider+Toast.Viewport) alongside a modalDialog. - In one handler, fire a toast that carries a
ToastAction, and open the dialog. - With the dialog open, inspect the action button: it is visible, it has
pointer-events: auto, and an ancestor carriesaria-hidden="true".
Why it matters
The toast in our case carries the Undo for the action that opened the dialog. A sighted mouse user can still take it back; a screen-reader user cannot perceive that it is offered at all. The regression is silent — nothing renders differently and no error is thrown.
Environment
React 19, Next 16.3.0, shadcn/ui toast, Chromium via Playwright 1.62.
Source: radix-ui/primitives