DEV: Do not trigger floatkit 'hover' for touch events (#30793)

When tapping something on a touch-enabled device, `mouseMove` events are
still fired, so floatkit would still be triggered even if configured for
'hover' only. For links, this would be particularly strange, because the
tooltip would appear for a split-second, before the page navigation
occured.

To avoid this problem, we can use the more-modern 'pointerMove' event,
and check the `pointerType` to exclude 'touch'
This commit is contained in:
David Taylor
2025-01-16 12:36:47 +00:00
committed by GitHub
parent f28eb5b0dc
commit 72f4588d3b
9 changed files with 29 additions and 18 deletions

View File

@ -155,7 +155,7 @@ acceptance("Post inline mentions – user status tooltip", function (needs) {
}; };
async function mouseMove(selector) { async function mouseMove(selector) {
await triggerEvent(selector, "mousemove"); await triggerEvent(selector, "pointermove");
} }
test("shows user status tooltip", async function (assert) { test("shows user status tooltip", async function (assert) {

View File

@ -46,7 +46,7 @@ module("Integration | Component | DStatTiles", function (hooks) {
</template>); </template>);
assert.dom(".d-stat-tile__tooltip").exists(); assert.dom(".d-stat-tile__tooltip").exists();
await triggerEvent(".fk-d-tooltip__trigger", "mousemove"); await triggerEvent(".fk-d-tooltip__trigger", "pointermove");
assert.dom(".fk-d-tooltip__content").hasText(i18n("bootstrap_mode")); assert.dom(".fk-d-tooltip__content").hasText(i18n("bootstrap_mode"));
}); });

View File

@ -15,11 +15,11 @@ module("Integration | Component | FloatKit | d-tooltip", function (hooks) {
setupRenderingTest(hooks); setupRenderingTest(hooks);
async function hover() { async function hover() {
await triggerEvent(".fk-d-tooltip__trigger", "mousemove"); await triggerEvent(".fk-d-tooltip__trigger", "pointermove");
} }
async function leave() { async function leave() {
await triggerEvent(".fk-d-tooltip__trigger", "mouseleave"); await triggerEvent(".fk-d-tooltip__trigger", "pointerleave");
} }
async function close() { async function close() {

View File

@ -127,7 +127,7 @@ module("Integration | Component | user-info", function (hooks) {
await render( await render(
hbs`<UserInfo @user={{this.currentUser}} @showStatus={{true}} /><DTooltips />` hbs`<UserInfo @user={{this.currentUser}} @showStatus={{true}} /><DTooltips />`
); );
await triggerEvent(query(".user-status-message"), "mousemove"); await triggerEvent(query(".user-status-message"), "pointermove");
assert assert
.dom("[data-content][data-identifier='user-status-message-tooltip']") .dom("[data-content][data-identifier='user-status-message-tooltip']")

View File

@ -5,7 +5,7 @@ import { setupRenderingTest } from "discourse/tests/helpers/component-test";
import { fakeTime, query } from "discourse/tests/helpers/qunit-helpers"; import { fakeTime, query } from "discourse/tests/helpers/qunit-helpers";
async function mouseenter() { async function mouseenter() {
await triggerEvent(query(".user-status-message"), "mousemove"); await triggerEvent(query(".user-status-message"), "pointermove");
} }
module("Integration | Component | user-status-message", function (hooks) { module("Integration | Component | user-status-message", function (hooks) {

View File

@ -81,7 +81,7 @@ export default class DMenuInstance extends FloatKitInstance {
} }
@action @action
async onMouseMove(event) { async onPointerMove(event) {
if (this.expanded && this.trigger.contains(event.target)) { if (this.expanded && this.trigger.contains(event.target)) {
return; return;
} }
@ -99,7 +99,7 @@ export default class DMenuInstance extends FloatKitInstance {
} }
@action @action
async onMouseLeave(event) { async onPointerLeave(event) {
if (this.untriggers.includes("hover")) { if (this.untriggers.includes("hover")) {
await this.onUntrigger(event); await this.onUntrigger(event);
} }

View File

@ -65,8 +65,12 @@ export default class DTooltipInstance extends FloatKitInstance {
} }
@action @action
async onMouseMove(event) { async onPointerMove(event) {
if (this.expanded && this.trigger.contains(event.target)) { if (
this.expanded &&
this.trigger.contains(event.target) &&
event.pointerType !== "touch"
) {
return; return;
} }
@ -83,7 +87,7 @@ export default class DTooltipInstance extends FloatKitInstance {
} }
@action @action
async onMouseLeave(event) { async onPointerLeave(event) {
if (this.untriggers.includes("hover")) { if (this.untriggers.includes("hover")) {
await this.onUntrigger(event); await this.onUntrigger(event);
} }

View File

@ -128,9 +128,12 @@ export default class FloatKitInstance {
this.trigger.removeEventListener("focusout", this.onFocusOut); this.trigger.removeEventListener("focusout", this.onFocusOut);
break; break;
case "hover": case "hover":
this.trigger.removeEventListener("mousemove", this.onMouseMove); this.trigger.removeEventListener("pointermove", this.onPointerMove);
if (!this.options.interactive) { if (!this.options.interactive) {
this.trigger.removeEventListener("mouseleave", this.onMouseLeave); this.trigger.removeEventListener(
"pointerleave",
this.onPointerLeave
);
} }
break; break;
@ -180,13 +183,17 @@ export default class FloatKitInstance {
}); });
break; break;
case "hover": case "hover":
this.trigger.addEventListener("mousemove", this.onMouseMove, { this.trigger.addEventListener("pointermove", this.onPointerMove, {
passive: true, passive: true,
}); });
if (!this.options.interactive) { if (!this.options.interactive) {
this.trigger.addEventListener("mouseleave", this.onMouseLeave, { this.trigger.addEventListener(
passive: true, "pointerleave",
}); this.onPointerLeave,
{
passive: true,
}
);
} }
break; break;

View File

@ -159,7 +159,7 @@ module(
test("it shows status tooltip", async function (assert) { test("it shows status tooltip", async function (assert) {
await render(hbs`<ChatChannel @channel={{this.channel}} /><DTooltips />`); await render(hbs`<ChatChannel @channel={{this.channel}} /><DTooltips />`);
await triggerEvent(statusSelector(mentionedUser.username), "mousemove"); await triggerEvent(statusSelector(mentionedUser.username), "pointermove");
assert assert
.dom(".user-status-tooltip-description") .dom(".user-status-tooltip-description")