Component
Dialog
Package version
9.73.7
React version
18
Environment
System:
OS: Windows 11 10.0.26100
CPU: (20) x64 12th Gen Intel(R) Core(TM) i9-12900H
Memory: 16.53 GB / 31.69 GB
Browsers:
Chrome: 146.0.7680.178
Edge: Chromium (142.0.3595.53)
Firefox: 149.0.2 - C:\Program Files\Mozilla Firefox\firefox.exe
Internet Explorer: 11.0.26100.7309
npmPackages:
@fluentui/react-components: ^9.0.0 => 9.72.9
@fluentui/react-icons: ^2.0.312 => 2.0.316
@types/react: ^17 => 17.0.90
@types/react-dom: ^17.0.26 => 17.0.26
react: ^18 => 18.3.1
react-dom: ^18 => 18.3.1
Current Behavior
When two or more independent (non-nested) Dialog components are stacked, closing the top dialog leaves the underlying dialog with a stale aria-hidden="true" on its portal node. This breaks the focus trap — focus jumps back to the original page trigger instead of returning to the underlying dialog.
Root cause (investigation)
Tabster's modalizer sets aria-hidden="true" on everything outside the active dialog. When the top dialog unmounts, the modalizer doesn't clean up the stale attribute on the underlying dialog's portal. The browser then blocks focus restoration into the aria-hidden subtree.
Workaround
We're using a useLayoutEffect hook that runs synchronously after the top dialog unmounts to:
Find the topmost remaining dialog by z-index
Remove aria-hidden from its portal container
Focus the first real focusable element (excluding [data-tabster-dummy])
This works but relies on internal DOM structure and is fragile against future changes.
Expected Behavior
Closing the top dialog should restore focus to the underlying dialog and its focus trap should re-engage.
Reproduction
https://stackblitz.com/edit/pxkb6cxd?file=src%2FApp.tsx
Steps to reproduce
- Render two independent Dialog components (not nested — siblings at the root level)
- Open Dialog 1
- From inside Dialog 1, programmatically open Dialog 2 (modalType="alert")
- Close Dialog 2
- Focus should return to Dialog 1, but instead it jumps to the page-level trigger button
Are you reporting an Accessibility issue?
None
Suggested severity
Medium - Has workaround
Products/sites affected
No response
Are you willing to submit a PR to fix?
no
Validations
Component
Dialog
Package version
9.73.7
React version
18
Environment
System: OS: Windows 11 10.0.26100 CPU: (20) x64 12th Gen Intel(R) Core(TM) i9-12900H Memory: 16.53 GB / 31.69 GB Browsers: Chrome: 146.0.7680.178 Edge: Chromium (142.0.3595.53) Firefox: 149.0.2 - C:\Program Files\Mozilla Firefox\firefox.exe Internet Explorer: 11.0.26100.7309 npmPackages: @fluentui/react-components: ^9.0.0 => 9.72.9 @fluentui/react-icons: ^2.0.312 => 2.0.316 @types/react: ^17 => 17.0.90 @types/react-dom: ^17.0.26 => 17.0.26 react: ^18 => 18.3.1 react-dom: ^18 => 18.3.1Current Behavior
When two or more independent (non-nested) Dialog components are stacked, closing the top dialog leaves the underlying dialog with a stale aria-hidden="true" on its portal node. This breaks the focus trap — focus jumps back to the original page trigger instead of returning to the underlying dialog.
Root cause (investigation)
Tabster's modalizer sets aria-hidden="true" on everything outside the active dialog. When the top dialog unmounts, the modalizer doesn't clean up the stale attribute on the underlying dialog's portal. The browser then blocks focus restoration into the aria-hidden subtree.
Workaround
We're using a useLayoutEffect hook that runs synchronously after the top dialog unmounts to:
Find the topmost remaining dialog by z-index
Remove aria-hidden from its portal container
Focus the first real focusable element (excluding [data-tabster-dummy])
This works but relies on internal DOM structure and is fragile against future changes.
Expected Behavior
Closing the top dialog should restore focus to the underlying dialog and its focus trap should re-engage.
Reproduction
https://stackblitz.com/edit/pxkb6cxd?file=src%2FApp.tsx
Steps to reproduce
Are you reporting an Accessibility issue?
None
Suggested severity
Medium - Has workaround
Products/sites affected
No response
Are you willing to submit a PR to fix?
no
Validations