Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(tooltip, popover): honor prevented events #11278

Merged
merged 5 commits into from
Jan 15, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ export default class PopoverManager {
};

private clickHandler = (event: PointerEvent): void => {
if (isKeyboardTriggeredClick(event)) {
if (isKeyboardTriggeredClick(event) || event.defaultPrevented) {
return;
}

Expand Down
29 changes: 29 additions & 0 deletions packages/calcite-components/src/components/popover/popover.e2e.ts
Original file line number Diff line number Diff line change
Expand Up @@ -368,6 +368,35 @@ describe("calcite-popover", () => {
expect(await popover.getProperty("open")).toBe(true);
});

it("should not open popovers if event is prevented", async () => {
const page = await newE2EPage();

await page.setContent(html`
<calcite-popover reference-element="ref">Content</calcite-popover>
<div id="ref">Button</div>
`);

await page.waitForChanges();

const popover = await page.find("calcite-popover");

expect(await popover.getProperty("open")).toBe(false);

await page.$eval("#ref", (ref) => {
ref.addEventListener("click", (event) => {
event.preventDefault();
});
});

const referenceElement = await page.find("#ref");

await referenceElement.click();

await page.waitForChanges();

expect(await popover.getProperty("open")).toBe(false);
});

it("should not be visible if reference is hidden", async () => {
const page = await newE2EPage();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,10 @@ export default class TooltipManager {
};

private pointerMoveHandler = (event: PointerEvent): void => {
if (event.defaultPrevented) {
return;
}

const composedPath = event.composedPath();
const { activeTooltip } = this;

Expand Down Expand Up @@ -129,6 +133,10 @@ export default class TooltipManager {
}

private clickHandler = (event: Event): void => {
if (event.defaultPrevented) {
return;
}

this.clickedTooltip = null;
const composedPath = event.composedPath();
const tooltip = this.queryTooltip(composedPath);
Expand Down Expand Up @@ -160,6 +168,10 @@ export default class TooltipManager {
};

private focusInHandler = (event: FocusEvent): void => {
if (event.defaultPrevented) {
return;
}

const composedPath = event.composedPath();
const tooltip = this.queryTooltip(composedPath);

Expand Down
114 changes: 114 additions & 0 deletions packages/calcite-components/src/components/tooltip/tooltip.e2e.ts
Original file line number Diff line number Diff line change
Expand Up @@ -320,6 +320,34 @@ describe("calcite-tooltip", () => {
expect(await positionContainer.isVisible()).toBe(true);
});

it("should not open when hover event is prevented", async () => {
const page = await newE2EPage();

await page.setContent(
`<calcite-tooltip reference-element="ref">content</calcite-tooltip><div id="ref">referenceElement</div>`,
);

await page.waitForChanges();

const positionContainer = await page.find(`calcite-tooltip >>> .${CSS.positionContainer}`);

expect(await positionContainer.isVisible()).toBe(false);

await page.$eval("#ref", (ref) => {
ref.addEventListener("pointermove", (event) => {
event.preventDefault();
});
});

const ref = await page.find("#ref");

await ref.hover();

await page.waitForTimeout(TOOLTIP_OPEN_DELAY_MS);

expect(await positionContainer.isVisible()).toBe(false);
});

it("should honor hover interaction with span inside", async () => {
const page = await newE2EPage();

Expand Down Expand Up @@ -426,6 +454,34 @@ describe("calcite-tooltip", () => {
expect(await tooltip.getProperty("open")).toBe(false);
});

it("should not open if focus event is prevented", async () => {
const page = await newE2EPage();

await page.setContent(html`
<button id="test">test</button>
<calcite-tooltip reference-element="ref">Content</calcite-tooltip>
<button id="ref">Button</button>
`);

await page.waitForChanges();

const tooltip = await page.find("calcite-tooltip");

expect(await tooltip.getProperty("open")).toBe(false);

await page.$eval("#ref", (ref) => {
ref.addEventListener("focusin", (event) => {
event.preventDefault();
});

ref.dispatchEvent(new FocusEvent("focusin", { bubbles: true, cancelable: true }));
});

await page.waitForChanges();

expect(await tooltip.getProperty("open")).toBe(false);
});

it("should handle mouse events", async () => {
const page = await newE2EPage();

Expand Down Expand Up @@ -547,6 +603,45 @@ describe("calcite-tooltip", () => {
await assertEscapeKeyCanceled(page, true);
});

it("should not close with ESC key if event is prevented", async () => {
const page = await newE2EPage();

await page.setContent(html`
<calcite-tooltip reference-element="ref">Content</calcite-tooltip>
<button id="ref">Button</button>
`);

await page.waitForChanges();

const tooltip = await page.find("calcite-tooltip");

expect(await tooltip.getProperty("open")).toBe(false);

const referenceElement = await page.find("#ref");

await referenceElement.focus();

await referenceElement.hover();

await page.waitForTimeout(TOOLTIP_OPEN_DELAY_MS);

await page.waitForChanges();

expect(await tooltip.getProperty("open")).toBe(true);

await page.evaluate(() => {
document.body.addEventListener("keydown", (event) => {
if (event.key === "Escape") {
event.preventDefault();
}
});
});

await dispatchKeydownEvent(page, "#ref", "Escape");

expect(await tooltip.getProperty("open")).toBe(true);
});

it("should only open the last focused tooltip", async () => {
const page = await newE2EPage();

Expand Down Expand Up @@ -1175,6 +1270,25 @@ describe("calcite-tooltip", () => {
expect(await tooltip.getProperty("open")).toBe(false);
});

it("should not open when click event is prevented", async () => {
const page = await newE2EPage();
await page.setContent(pageContent);
await skipAnimations(page);
await page.waitForChanges();
const tooltip = await page.find("calcite-tooltip");

await page.$eval("#ref", (ref) => {
ref.addEventListener("click", (event) => {
event.preventDefault();
});

ref.dispatchEvent(new MouseEvent("click", { bubbles: true, cancelable: true }));
});

await page.waitForChanges();
expect(await tooltip.getProperty("open")).toBe(false);
});

it("should work when focusing on a reference element first", async () => {
const page = await newE2EPage();
await page.setContent(pageContent);
Expand Down
Loading