fix(desktop): dedupe react-dismissable-layer to stop modal menu → dialog freezes#1899
Merged
Conversation
…ntext menu
Setting a reminder from the inbox row right-click menu left
`pointer-events: none` stuck on <body> once the dialog closed, deadening
the whole app to the mouse. The app bundles two copies of
@radix-ui/react-dismissable-layer (react-menu resolves 1.1.11,
react-dialog 1.1.15); each keeps its own module-level saved body style,
so the dialog's copy captured the modal ContextMenu's body lock as the
"original" value and restored it on close.
Fix: modal={false} on the inbox row ContextMenu — a non-modal menu
installs no body guard, so there is no second layer to fight the dialog.
Same pattern as #1482 for the sidebar channel menus.
Adds a regression spec covering all three reminder entry points
(message-menu preset, dialog footer Set reminder, inbox right-click);
the inbox right-click test fails without the fix and passes with it.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Signed-off-by: Matt Toohey <contact@matttoohey.com>
…l={false}
Follow-up to the inbox reminder freeze fix: the root cause was two
bundled copies of @radix-ui/react-dismissable-layer (react-menu resolved
1.1.11, react-dialog 1.1.15), each keeping its own module-level saved
<body> pointer-events style — so any modal menu opening a modal dialog
left `pointer-events: none` stuck on <body> when the dialog closed,
freezing the app.
Pin the layer to a single version with a pnpm override in
pnpm-workspace.yaml, fixing the whole class at the source: one copy
coordinates nested modal layers correctly, and the built bundle now
contains exactly one copy of the module.
Revert the per-menu modal={false} workarounds this makes obsolete — the
inbox row ContextMenu (previous commit) and the three sidebar
channel/section menus from #1482 — restoring the menus' default modal
behavior. Both regression suites prove the dedupe covers them:
reminder-click-repro.spec.ts and the sidebar leave-channel guard pass
with the menus modal again, and fail if the layer ever duplicates.
The lockfile re-resolution also collapsed a duplicated @floating-ui
core/dom/utils trio as a side effect.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Signed-off-by: Matt Toohey <contact@matttoohey.com>
wesbillman
approved these changes
Jul 15, 2026
tlongwell-block
pushed a commit
that referenced
this pull request
Jul 15, 2026
* origin/main: (21 commits) refactor(desktop): unify page/section header hierarchy across Agents and Settings (#1912) chore(release): release Buzz Desktop version 0.4.6 (#1911) fix(desktop): restore chat-first agent creation after mesh rebase (#1909) feat(relay): add community unarchive endpoint (#1908) Polish agent and team sharing and snapshots (#1852) fix(buzz-acp): distinguish cancel-drain expiry from real hard-cap timeout (#1893) fix(desktop): filter punctuation from avatar initials (#1904) fix(desktop): preserve snapshot attachment URLs (#1905) Chat-first agent creation via portable buzz CLI drafts (#1878) feat(desktop): enable community rail by default (#1902) feat(desktop): redesign Nostr bind verification flow (#1850) fix(desktop): simplify sign out settings row (#1903) chore(deps): update rust crate reqwest to v0.13.4 (#1792) feat(relay): gate Git web GUI separately (#1901) feat(desktop): Send feedback modal + profile presence chip (#1756) fix(desktop): seed timeline virtualization row heights (#1887) fix(desktop): dedupe react-dismissable-layer to stop modal menu → dialog freezes (#1899) fix(desktop): clean up Remind me later dialog footer and loading state (#1898) fix(desktop): let sidebar action card description wrap over multiple lines (#1891) mesh: upgrade runtime, enforce membership, add shared compute provider (#1656) ...
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 free
to 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.
Summary
Broken behaviour:
Context.menu.breaks.mov
Setting a reminder from the inbox row's right-click menu left
pointer-events: nonestuck on<body>after the reminder dialog closed, deadening the entire app to mouse input.Root cause: the app bundled two copies of
@radix-ui/react-dismissable-layer(react-menuresolved 1.1.11,react-dialog1.1.15). Each copy keeps its own module-level saved body style, so whenever a modal menu opened a modal dialog, the dialog's copy captured the menu's body lock as the "original" value and restored it on close — leavingpointer-events: nonepermanently applied to<body>. Every modal menu → modal dialog path in the app was exposed to this, not just the inbox reminder (#1482 hit the same class from the sidebar Leave-channel menu).Fix: dedupe the layer at the source with a pnpm override in
pnpm-workspace.yamlpinning@radix-ui/react-dismissable-layerto a single version. One copy coordinates nested modal layers correctly, fixing the whole class — the built bundle now contains exactly one copy of the module.The lockfile re-resolution also collapsed a duplicated
@floating-uicore/dom/utils trio as a side effect.Testing
desktop/tests/e2e/reminder-click-repro.spec.tscovering all three reminder entry points (message-menu preset, dialog footer "Set reminder", inbox right-click), registered inplaywright.config.ts. The inbox right-click test drives the exact modal-menu → modal-dialog stack, so it fails if the dismissable layer ever duplicates again.reminder-click-repro.spec.ts(3/3) andsidebar.spec.tsincluding the fix(desktop): stop Leave-channel dialog from freezing the app #1482 leave-channel freeze guard (7/7).pnpm check,tsc --noEmit, all 2,885 desktop unit tests, and theweb/build (also covered by the workspace override) pass.🤖 Generated with Claude Code