Close RTE dropdowns on mousedown instead of click#5926
Conversation
ProseMirror calls preventDefault() on mouseup when repositioning the cursor, and ToolbarButton uses @mousedown.prevent — both suppress the click event per the HTML spec. Switching the document listener to mousedown makes dropdown close reliable for all interactions inside the editor. Fixes learningequality#5886 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
48c8e59 to
1cc7d04
Compare
rtibblesbot
left a comment
There was a problem hiding this comment.
Clean fix with a thorough root cause analysis.
CI passing. No UI files changed — visual inspection not applicable.
- praise: see inline
|
|
||
| onMounted(() => { | ||
| document.addEventListener('click', handleClickOutside); | ||
| document.addEventListener('mousedown', handleClickOutside); |
There was a problem hiding this comment.
praise: The root cause analysis here is excellent — tracing the missing click events to two independent preventDefault() paths (ProseMirror's mouseup and ToolbarButton's @mousedown.prevent) and choosing mousedown as the fix point is well-reasoned. The change is minimal and precise.
|
@rtibblesbot's comments are generated by an LLM, and should be evaluated accordingly How was this generated?Reviewed the pull request diff checking for:
|
There was a problem hiding this comment.
Changes make sense to me, and manual QA confirms. The only small nitpick is that in the useDropdowns composable, we check all open dropdowns to confirm the click is outside, which leads to the dropdown not being closed if you are opening another dropdown (which should be)
Grabacion.de.pantalla.2026-05-21.a.la.s.10.10.34.a.m.mov
In general, I wonder whether we should use KDropdownMenu here, which already handles many of these things? cc: @marcellamaki @rtibbles. (not that we should do it in this PR to hotfixes, but in a follow-up to unstable, or in #5707 where we'll also need to make some decisions around these dropdowns)
|
Yes - I think that's reasonable, and having it be able to handle the specific styling/layout constraints that would be required for it in the RTE seems like good disciplining for the component! |
Summary
Root cause: Two separate
preventDefault()calls suppress theclickevent inside the editor, per the HTML spec:ToolbarButton.vueuses@mousedown.preventon every toolbar button — this preventsclickfrom firing after any toolbar button presspreventDefault()onmouseupwhen repositioning the cursor — this preventsclickfrom firing when clicking into the editor content areaHow it works: Switched the document-level
handleClickOutsidelistener from'click'to'mousedown'inuseDropdowns.js(font & paste dropdowns) andEditorToolbar.vue(More overflow dropdown). Themousedownevent always propagates to the document regardless of anypreventDefault()calls, making dropdown closing reliable for all interactions.Screen.Recording.2026-05-20.at.11.09.34.mov
References
Fixes #5886
Reviewer guidance
AI usage
Implemented with Claude Code. I reviewed the generated diff and confirmed the root cause analysis (ProseMirror
mouseuppreventDefault + ToolbarButton@mousedown.preventboth suppressingclickevents).