Skip to content

Commit 106f5d2

Browse files
authored
fix(tooltip): improve component timing (#7172)
**Related Issue:** #6396 ## Summary - Separates timeout delay between open and close. - `open` is set to `300ms`. - `close` is set to `500ms`. - Sets delay to `0ms` if a tooltip is already displayed. - Add story for design review. - Update tests.
1 parent 0e2a205 commit 106f5d2

File tree

5 files changed

+142
-50
lines changed

5 files changed

+142
-50
lines changed

packages/calcite-components/src/components/action-bar/action-bar.stories.ts

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,36 @@ export const darkModeRTL_TestOnly = (): string =>
148148

149149
darkModeRTL_TestOnly.parameters = { modes: modesDarkDefault };
150150

151+
export const adjacentTooltipsOpenQuickly = (): string => html`<div style="display:flex; height:500px; width: 200px;">
152+
<calcite-action-bar>
153+
<calcite-action-group>
154+
<calcite-action text="Add" icon="plus">
155+
<calcite-tooltip placement="right" slot="tooltip">Add</calcite-tooltip>
156+
</calcite-action>
157+
<calcite-action text="Save" icon="save"
158+
><calcite-tooltip placement="right" slot="tooltip">Save</calcite-tooltip></calcite-action
159+
>
160+
<calcite-action text="Layers" icon="layers"
161+
><calcite-tooltip placement="right" slot="tooltip">Layers</calcite-tooltip></calcite-action
162+
>
163+
</calcite-action-group>
164+
<calcite-action-group>
165+
<calcite-action text="Add" icon="plus"
166+
><calcite-tooltip placement="right" slot="tooltip">Add</calcite-tooltip></calcite-action
167+
>
168+
<calcite-action text="Save" active icon="save"
169+
><calcite-tooltip placement="right" slot="tooltip">Save</calcite-tooltip></calcite-action
170+
>
171+
<calcite-action text="Layers" icon="layers"
172+
><calcite-tooltip placement="right" slot="tooltip">Layers</calcite-tooltip></calcite-action
173+
>
174+
</calcite-action-group>
175+
<calcite-action slot="bottom-actions" text="hello world" icon="layers"
176+
><calcite-tooltip placement="right" slot="tooltip">hello world</calcite-tooltip></calcite-action
177+
>
178+
</calcite-action-bar>
179+
</div>`;
180+
151181
export const withTooltip_NoTest = (): string =>
152182
create(
153183
"calcite-action-bar",

packages/calcite-components/src/components/action-menu/action-menu.e2e.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { newE2EPage } from "@stencil/core/testing";
22
import { html } from "../../../support/formatting";
33
import { accessible, defaults, focusable, hidden, reflects, renders, slots } from "../../tests/commonTests";
4-
import { TOOLTIP_DELAY_MS } from "../tooltip/resources";
4+
import { TOOLTIP_OPEN_DELAY_MS } from "../tooltip/resources";
55
import { CSS, SLOTS } from "./resources";
66

77
describe("calcite-action-menu", () => {
@@ -198,7 +198,7 @@ describe("calcite-action-menu", () => {
198198
expect(await tooltip.isVisible()).toBe(false);
199199

200200
await trigger.hover();
201-
await page.waitForTimeout(TOOLTIP_DELAY_MS);
201+
await page.waitForTimeout(TOOLTIP_OPEN_DELAY_MS);
202202

203203
expect(await tooltip.isVisible()).toBe(true);
204204

packages/calcite-components/src/components/tooltip/TooltipManager.ts

Lines changed: 52 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { getShadowRootNode, isPrimaryPointerButton } from "../../utils/dom";
22
import { ReferenceElement } from "../../utils/floating-ui";
3-
import { TOOLTIP_DELAY_MS } from "./resources";
3+
import { TOOLTIP_OPEN_DELAY_MS, TOOLTIP_CLOSE_DELAY_MS } from "./resources";
44
import { getEffectiveReferenceElement } from "./utils";
55

66
export default class TooltipManager {
@@ -14,7 +14,9 @@ export default class TooltipManager {
1414

1515
private registeredShadowRootCounts = new WeakMap<ShadowRoot, number>();
1616

17-
private hoverTimeout: number = null;
17+
private hoverOpenTimeout: number = null;
18+
19+
private hoverCloseTimeout: number = null;
1820

1921
private hoveredTooltip: HTMLCalciteTooltipElement = null;
2022

@@ -80,7 +82,7 @@ export default class TooltipManager {
8082

8183
if (activeTooltip?.open) {
8284
this.clearHoverTimeout();
83-
this.closeExistingTooltip();
85+
this.closeActiveTooltip();
8486

8587
const referenceElement = getEffectiveReferenceElement(activeTooltip);
8688

@@ -111,9 +113,9 @@ export default class TooltipManager {
111113
this.clickedTooltip = null;
112114

113115
if (tooltip) {
114-
this.toggleHoveredTooltip(tooltip, true);
116+
this.openHoveredTooltip(tooltip);
115117
} else if (activeTooltip) {
116-
this.toggleHoveredTooltip(activeTooltip, false);
118+
this.closeHoveredTooltip();
117119
}
118120
};
119121

@@ -166,61 +168,83 @@ export default class TooltipManager {
166168
document.removeEventListener("focusout", this.focusOutHandler, { capture: true });
167169
}
168170

171+
private clearHoverOpenTimeout(): void {
172+
window.clearTimeout(this.hoverOpenTimeout);
173+
this.hoverOpenTimeout = null;
174+
}
175+
176+
private clearHoverCloseTimeout(): void {
177+
window.clearTimeout(this.hoverCloseTimeout);
178+
this.hoverCloseTimeout = null;
179+
}
180+
169181
private clearHoverTimeout(): void {
170-
window.clearTimeout(this.hoverTimeout);
171-
this.hoverTimeout = null;
182+
this.clearHoverOpenTimeout();
183+
this.clearHoverCloseTimeout();
172184
}
173185

174-
private closeExistingTooltip(): void {
186+
private closeActiveTooltip(): void {
175187
const { activeTooltip } = this;
176188

177189
if (activeTooltip?.open) {
178190
this.toggleTooltip(activeTooltip, false);
179191
}
180192
}
181193

182-
private toggleFocusedTooltip(tooltip: HTMLCalciteTooltipElement, value: boolean): void {
183-
this.closeExistingTooltip();
194+
private toggleFocusedTooltip(tooltip: HTMLCalciteTooltipElement, open: boolean): void {
195+
this.closeActiveTooltip();
184196

185-
if (value) {
197+
if (open) {
186198
this.clearHoverTimeout();
187199
}
188200

189-
this.toggleTooltip(tooltip, value);
201+
this.toggleTooltip(tooltip, open);
190202
}
191203

192-
private toggleTooltip(tooltip: HTMLCalciteTooltipElement, value: boolean): void {
193-
tooltip.open = value;
204+
private toggleTooltip(tooltip: HTMLCalciteTooltipElement, open: boolean): void {
205+
tooltip.open = open;
194206

195-
if (value) {
196-
this.activeTooltip = tooltip;
197-
}
207+
this.activeTooltip = open ? tooltip : null;
198208
}
199209

200-
private toggleHoveredTooltip = (tooltip: HTMLCalciteTooltipElement, value: boolean): void => {
201-
this.hoverTimeout = window.setTimeout(() => {
202-
if (this.hoverTimeout === null) {
203-
return;
204-
}
210+
private openHoveredTooltip = (tooltip: HTMLCalciteTooltipElement): void => {
211+
this.hoverOpenTimeout = window.setTimeout(
212+
() => {
213+
if (this.hoverOpenTimeout === null) {
214+
return;
215+
}
216+
217+
this.clearHoverCloseTimeout();
218+
this.closeActiveTooltip();
205219

206-
this.closeExistingTooltip();
220+
if (tooltip !== this.hoveredTooltip) {
221+
return;
222+
}
223+
224+
this.toggleTooltip(tooltip, true);
225+
},
226+
this.activeTooltip ? 0 : TOOLTIP_OPEN_DELAY_MS
227+
);
228+
};
207229

208-
if (tooltip !== this.hoveredTooltip) {
230+
private closeHoveredTooltip = (): void => {
231+
this.hoverCloseTimeout = window.setTimeout(() => {
232+
if (this.hoverCloseTimeout === null) {
209233
return;
210234
}
211235

212-
this.toggleTooltip(tooltip, value);
213-
}, TOOLTIP_DELAY_MS);
236+
this.closeActiveTooltip();
237+
}, TOOLTIP_CLOSE_DELAY_MS);
214238
};
215239

216-
private queryFocusedTooltip(event: FocusEvent, value: boolean): void {
240+
private queryFocusedTooltip(event: FocusEvent, open: boolean): void {
217241
const tooltip = this.queryTooltip(event.composedPath());
218242

219243
if (!tooltip || this.isClosableClickedTooltip(tooltip)) {
220244
return;
221245
}
222246

223-
this.toggleFocusedTooltip(tooltip, value);
247+
this.toggleFocusedTooltip(tooltip, open);
224248
}
225249

226250
private isClosableClickedTooltip(tooltip: HTMLCalciteTooltipElement): boolean {

packages/calcite-components/src/components/tooltip/resources.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ export const CSS = {
22
container: "container"
33
};
44

5-
export const TOOLTIP_DELAY_MS = 500;
5+
export const TOOLTIP_OPEN_DELAY_MS = 300;
6+
export const TOOLTIP_CLOSE_DELAY_MS = 500;
67

78
export const ARIA_DESCRIBED_BY = "aria-describedby";

0 commit comments

Comments
 (0)