From a3c144ce626b6f11a85d4400d1612694e4b8d4de Mon Sep 17 00:00:00 2001 From: Matt Driscoll Date: Mon, 5 Aug 2024 16:28:26 -0700 Subject: [PATCH] feat(tooltip): allow focusing and clicking on interactive elements within a tooltip (#9914) **Related Issue:** #6298 ## Summary - Allows placing interactive elements in tooltip elements with the following caveats - It should be advised against placing interactive elements within a tooltip because there is no a11y guidelines for accessing interactive elements within a tooltip role. Ideally a popover should be used for interactive elements. - No focus trapping or focus will be brought to interactive elements within the tooltip. - You can tab to a focusable element within a tooltip if the tooltip with the focusable element is the next focusable element within the DOM order. Otherwise, you could listen for the tooltip to be open and focus on the first interactive element if you wanted to do so. - add test - add story --- .../src/components/tooltip/TooltipManager.ts | 5 +++++ .../src/components/tooltip/tooltip.e2e.ts | 12 +++++++++++- .../src/components/tooltip/tooltip.stories.ts | 9 +++++++++ 3 files changed, 25 insertions(+), 1 deletion(-) diff --git a/packages/calcite-components/src/components/tooltip/TooltipManager.ts b/packages/calcite-components/src/components/tooltip/TooltipManager.ts index 5ee59a8df6b..302841ebb1e 100644 --- a/packages/calcite-components/src/components/tooltip/TooltipManager.ts +++ b/packages/calcite-components/src/components/tooltip/TooltipManager.ts @@ -148,6 +148,11 @@ export default class TooltipManager { const composedPath = event.composedPath(); const tooltip = this.queryTooltip(composedPath); + if (this.pathHasOpenTooltip(tooltip, composedPath)) { + this.clearHoverTimeout(); + return; + } + this.closeTooltipIfNotActive(tooltip); if (!tooltip) { diff --git a/packages/calcite-components/src/components/tooltip/tooltip.e2e.ts b/packages/calcite-components/src/components/tooltip/tooltip.e2e.ts index cf8d0c4b271..ba6e2a67b46 100644 --- a/packages/calcite-components/src/components/tooltip/tooltip.e2e.ts +++ b/packages/calcite-components/src/components/tooltip/tooltip.e2e.ts @@ -1127,7 +1127,7 @@ describe("calcite-tooltip", () => { describe("allows clicking on an open tooltip", () => { const pageContent = html` - content + content `; @@ -1147,6 +1147,11 @@ describe("calcite-tooltip", () => { await page.waitForChanges(); expect(await tooltip.getProperty("open")).toBe(true); + const button = await page.find("button"); + await button.click(); + await page.waitForChanges(); + expect(await tooltip.getProperty("open")).toBe(true); + await dispatchClickEvent(page, "#other"); expect(await tooltip.getProperty("open")).toBe(false); }); @@ -1166,6 +1171,11 @@ describe("calcite-tooltip", () => { await page.waitForChanges(); expect(await tooltip.getProperty("open")).toBe(true); + const button = await page.find("button"); + await button.focus(); + await page.waitForChanges(); + expect(await tooltip.getProperty("open")).toBe(true); + const other = await page.find("#other"); await other.focus(); await page.waitForChanges(); diff --git a/packages/calcite-components/src/components/tooltip/tooltip.stories.ts b/packages/calcite-components/src/components/tooltip/tooltip.stories.ts index 4f62fbd4a2c..eeedd5f1bd4 100644 --- a/packages/calcite-components/src/components/tooltip/tooltip.stories.ts +++ b/packages/calcite-components/src/components/tooltip/tooltip.stories.ts @@ -1,6 +1,7 @@ import { html } from "../../../support/formatting"; import { placements } from "../../utils/floating-ui"; import { boolean, modesDarkDefault } from "../../../.storybook/utils"; +import { placeholderImage } from "../../../.storybook/placeholderImage"; import { Tooltip } from "./tooltip"; const contentHTML = `Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua`; @@ -93,3 +94,11 @@ export const transparentBG_TestOnly = (): string => html` ${contentHTML} `; + +export const withInteractiveContent = (): string => + html`
+ ${referenceElementHTML} +

${contentHTML}

Click me +
`;