Skip to content

Commit

Permalink
feat(tooltip): Add tooltip open, close, beforeOpen, and beforeClose e…
Browse files Browse the repository at this point in the history
…vents (#5772)

feat(tooltip): Add tooltip open, close, beforeOpen, and beforeClose events. (#5734)
  • Loading branch information
driskull authored Nov 18, 2022
1 parent c68cd92 commit 64b5675
Show file tree
Hide file tree
Showing 2 changed files with 123 additions and 2 deletions.
58 changes: 58 additions & 0 deletions src/components/tooltip/tooltip.e2e.ts
Original file line number Diff line number Diff line change
Expand Up @@ -626,4 +626,62 @@ describe("calcite-tooltip", () => {

expect(await tooltip.isVisible()).toBe(true);
});

it("should emit open and beforeOpen events", async () => {
const page = await newE2EPage();
await page.setContent(
`<calcite-tooltip placement="auto" reference-element="ref">content</calcite-tooltip><div id="ref">referenceElement</div>`
);
const tooltip = await page.find("calcite-tooltip");

const openEvent = await tooltip.spyOnEvent("calciteTooltipOpen");
const beforeOpenEvent = await tooltip.spyOnEvent("calciteTooltipBeforeOpen");

expect(openEvent).toHaveReceivedEventTimes(0);
expect(beforeOpenEvent).toHaveReceivedEventTimes(0);

const tooltipOpenEvent = page.waitForEvent("calciteTooltipOpen");
const tooltipBeforeOpenEvent = page.waitForEvent("calciteTooltipBeforeOpen");

tooltip.setProperty("open", true);
await page.waitForChanges();

await tooltipOpenEvent;
await tooltipBeforeOpenEvent;

expect(openEvent).toHaveReceivedEventTimes(1);
expect(beforeOpenEvent).toHaveReceivedEventTimes(1);
});

it("should emit close and beforeClose events", async () => {
const page = await newE2EPage();

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

await page.waitForChanges();

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

const closeEvent = await tooltip.spyOnEvent("calciteTooltipClose");
const beforeCloseEvent = await tooltip.spyOnEvent("calciteTooltipBeforeClose");

expect(closeEvent).toHaveReceivedEventTimes(0);
expect(beforeCloseEvent).toHaveReceivedEventTimes(0);

const tooltipCloseEvent = page.waitForEvent("calciteTooltipClose");
const tooltipBeforeCloseEvent = page.waitForEvent("calciteTooltipBeforeClose");

await page.evaluate(() => {
const tooltip = document.querySelector("calcite-tooltip");
tooltip.open = false;
});

await tooltipBeforeCloseEvent;
await tooltipCloseEvent;

expect(closeEvent).toHaveReceivedEventTimes(1);
expect(beforeCloseEvent).toHaveReceivedEventTimes(1);
});
});
67 changes: 65 additions & 2 deletions src/components/tooltip/tooltip.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,16 @@
import { Component, Element, Host, Method, Prop, State, Watch, h, VNode } from "@stencil/core";
import {
Component,
Element,
Host,
Method,
Prop,
State,
Watch,
h,
VNode,
Event,
EventEmitter
} from "@stencil/core";
import { CSS, ARIA_DESCRIBED_BY } from "./resources";
import { guid } from "../../utils/guid";
import {
Expand All @@ -14,6 +26,11 @@ import {
updateAfterClose
} from "../../utils/floating-ui";
import { queryElementRoots, toAriaBoolean } from "../../utils/dom";
import {
OpenCloseComponent,
connectOpenCloseComponent,
disconnectOpenCloseComponent
} from "../../utils/openCloseComponent";

import TooltipManager from "./TooltipManager";

Expand All @@ -27,7 +44,7 @@ const manager = new TooltipManager();
styleUrl: "tooltip.scss",
shadow: true
})
export class Tooltip implements FloatingUIComponent {
export class Tooltip implements FloatingUIComponent, OpenCloseComponent {
// --------------------------------------------------------------------------
//
// Properties
Expand Down Expand Up @@ -133,13 +150,18 @@ export class Tooltip implements FloatingUIComponent {

hasLoaded = false;

openTransitionProp = "opacity";

transitionEl: HTMLDivElement;

// --------------------------------------------------------------------------
//
// Lifecycle
//
// --------------------------------------------------------------------------

connectedCallback(): void {
connectOpenCloseComponent(this);
this.setUpReferenceElement(this.hasLoaded);
}

Expand All @@ -154,8 +176,27 @@ export class Tooltip implements FloatingUIComponent {
disconnectedCallback(): void {
this.removeReferences();
disconnectFloatingUI(this, this.effectiveReferenceElement, this.el);
disconnectOpenCloseComponent(this);
}

//--------------------------------------------------------------------------
//
// Events
//
//--------------------------------------------------------------------------

/** Fires when the component is requested to be closed and before the closing transition begins. */
@Event({ cancelable: false }) calciteTooltipBeforeClose: EventEmitter<void>;

/** Fires when the component is closed and animation is complete. */
@Event({ cancelable: false }) calciteTooltipClose: EventEmitter<void>;

/** Fires when the component is added to the DOM but not rendered, and before the opening transition begins. */
@Event({ cancelable: false }) calciteTooltipBeforeOpen: EventEmitter<void>;

/** Fires when the component is open and animation is complete. */
@Event({ cancelable: false }) calciteTooltipOpen: EventEmitter<void>;

// --------------------------------------------------------------------------
//
// Public Methods
Expand Down Expand Up @@ -202,6 +243,27 @@ export class Tooltip implements FloatingUIComponent {
//
// --------------------------------------------------------------------------

onBeforeOpen(): void {
this.calciteTooltipBeforeOpen.emit();
}

onOpen(): void {
this.calciteTooltipOpen.emit();
}

onBeforeClose(): void {
this.calciteTooltipBeforeClose.emit();
}

onClose(): void {
this.calciteTooltipClose.emit();
}

private setTransitionEl = (el): void => {
this.transitionEl = el;
connectOpenCloseComponent(this);
};

setUpReferenceElement = (warn = true): void => {
this.removeReferences();
this.effectiveReferenceElement = this.getReferenceElement();
Expand Down Expand Up @@ -286,6 +348,7 @@ export class Tooltip implements FloatingUIComponent {
[FloatingCSS.animation]: true,
[FloatingCSS.animationActive]: displayed
}}
ref={this.setTransitionEl}
>
<div class={CSS.arrow} ref={(arrowEl) => (this.arrowEl = arrowEl)} />
<div class={CSS.container}>
Expand Down

0 comments on commit 64b5675

Please sign in to comment.