Repository navigation
Backdrops close on a click pressed and released on them, not a drag out of the dialog - #146
Merged
Merged
Conversation
…ut of the dialog A click whose press and release land on different elements is fired on their common ancestor, which for anything inside a modal is its backdrop. `@click.self` cannot tell, so selecting text in a dialog and letting go past its edge closed it, typed text and all (the ban dialog, the alert builder, the script editor, Mentions, the context menu, every settings-style window), and so did a press on the backdrop let go inside the dialog. The `v-backdrop` directive (helpers/backdrop.ts, registered in vue.ts) counts a click only when the pointer went down and came up on the backdrop itself, as a native <dialog>'s light dismiss does. It replaces every `@click.self` on an overlay and the click half of Mentions' and the context menu's own handlers; test/tests/backdrop.ts fails a new `@click.self`. The scenarios that closed an overlay with a bare `element.click()` now press it first. Tests: test/helpers/backdrop.ts; browser check tools/scenarios/backdrop-drag.mjs (fails on the old code).
After review. The directive keeps its two flags in closures and drops the update hook (every call site binds a stable function). Mentions' and the context menu's leftover handlers only closed on a right-click on the backdrop itself, which is `@contextmenu.self`. The static test is one assertion over every component. Scenarios close a backdrop with `clickBackdrop` (tools/scenarios/lib/backdrop.mjs), a real mouse press and release on a point where the backdrop is topmost, instead of three pasted synthetic-event snippets; backdrop-drag.mjs uses it and drops its reopen step.
rdrake
marked this pull request as ready for review
October 31, 2026 15:51
This branch was successfully deployed
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.
Selecting text in a modal and letting go past its edge closed the modal, along with anything typed in it.
Why
When the mouse button goes down on one element and up on another, the browser fires the click on their nearest common ancestor. For anything inside a modal, that ancestor is the backdrop.
@click.selfcan't tell such a click from a real one on the backdrop. Two cases closed the modal:The worst cases are the ban dialog and the alert builder, where the text the user typed is lost. The script editor, Mentions, the context menu and every settings-style window behaved the same way. Touch isn't affected, because a touch drag fires no click.
What
v-backdropdirective (client/js/helpers/backdrop.ts, registered invue.ts). It counts a click only when the pointer went down and came up on the backdrop itself, which is how a native<dialog>'s light dismiss behaves.@click.selfon an overlay, and the click half of Mentions' and the context menu's own handlers.@contextmenu.self.test/tests/backdrop.tsfails if@click.selfcomes back.<dialog>:closedbyisn't supported on iOS Safari, and moving to<dialog>would break the escape-layer ordering and the overlays' z-index scheme.clickBackdrop(tools/scenarios/lib/backdrop.mjs), a real mouse press and release. A bareelement.click()from script no longer closes anything, sohelp-modal,inboxandnative-shell-chromewere updated.Testing
test/helpers/backdrop.tscovers the directive's rules. The full mocha suite passes.tools/scenarios/backdrop-drag.mjspasses 7/7. On the old code the drag-out and press-in cases fail.help-modalandinboxpass.native-shell-chromefails one check ("the page is itself again with the shell off"), which fails the same way on develop.Mouse and trackpad only, so no phone testing is needed for the fix itself. The second commit is the review round; squash on merge if you prefer.