mirror of
https://github.com/discourse/discourse.git
synced 2025-02-25 18:55:32 -06:00
FIX: Propagate pointerdown events on DMenu trigger when the menu isn't expanded (#31104)
Stopping propagation when a `DMenu`'s trigger is clicked could prevent another floating UI element, e.g. the search menu in the header, from closing when clicking outside of it. We call `stopPropagation` on the event to allow more clicks within a `DMenu`'s trigger without it getting closed, so we shouldn't stop the event propagation if the `DMenu` hasn't been expanded yet.
This commit is contained in:
@@ -386,4 +386,46 @@ module("Integration | Component | FloatKit | d-menu", function (hooks) {
|
||||
|
||||
assert.dom(document.body).isFocused();
|
||||
});
|
||||
|
||||
test("traps pointerdown events only when expanded ", async function (assert) {
|
||||
let propagated = false;
|
||||
|
||||
const listener = () => {
|
||||
propagated = true;
|
||||
};
|
||||
|
||||
this.didInsert = (element) => {
|
||||
element.addEventListener("pointerdown", listener);
|
||||
};
|
||||
this.willDestroy = (element) => {
|
||||
element.removeEventListener("pointerdown", listener);
|
||||
};
|
||||
|
||||
await render(hbs`
|
||||
<div {{didInsert this.didInsert}} {{will-destroy this.willDestroy}}>
|
||||
<DMenu
|
||||
@inline={{true}}
|
||||
@label="label"
|
||||
@identifier="d-menu-pointerdown-trap-test"
|
||||
/>
|
||||
</div>
|
||||
`);
|
||||
|
||||
await triggerEvent(".d-menu-pointerdown-trap-test-trigger", "pointerdown");
|
||||
|
||||
assert.true(
|
||||
propagated,
|
||||
"the pointerdown event is propagated to the parent element when the menu isn't expanded"
|
||||
);
|
||||
|
||||
propagated = false;
|
||||
|
||||
await open();
|
||||
await triggerEvent(".d-menu-pointerdown-trap-test-trigger", "pointerdown");
|
||||
|
||||
assert.false(
|
||||
propagated,
|
||||
"the pointerdown event isn't propagated to the parent element when the menu is expanded"
|
||||
);
|
||||
});
|
||||
});
|
||||
|
@@ -53,6 +53,10 @@ export default class DMenuInstance extends FloatKitInstance {
|
||||
this.setupListeners();
|
||||
}
|
||||
|
||||
get shouldTrapPointerDown() {
|
||||
return this.expanded;
|
||||
}
|
||||
|
||||
@action
|
||||
async close(options = { focusTrigger: true }) {
|
||||
if (getOwner(this).isDestroying) {
|
||||
|
@@ -53,7 +53,9 @@ export default class FloatKitInstance {
|
||||
// this is done to avoid trigger on click outside when you click on your own trigger
|
||||
// given trigger and content are not in the same div, we can't just check if target is
|
||||
// inside the menu
|
||||
event.stopPropagation();
|
||||
if (this.shouldTrapPointerDown) {
|
||||
event.stopPropagation();
|
||||
}
|
||||
}
|
||||
|
||||
@action
|
||||
@@ -117,7 +119,7 @@ export default class FloatKitInstance {
|
||||
.forEach((trigger) => {
|
||||
switch (trigger) {
|
||||
case "hold":
|
||||
this.trigger.addEventListener("touchstart", this.onTouchStart);
|
||||
this.trigger.removeEventListener("touchstart", this.onTouchStart);
|
||||
break;
|
||||
case "focus":
|
||||
this.trigger.removeEventListener("focus", this.onFocus);
|
||||
@@ -231,4 +233,8 @@ export default class FloatKitInstance {
|
||||
|
||||
return this.options.untriggers ?? ["click"];
|
||||
}
|
||||
|
||||
get shouldTrapPointerDown() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user