Skip to content
This repository has been archived by the owner on Jan 13, 2025. It is now read-only.

Commit

Permalink
feat(tooltip): Plain tooltips remain visible if the user hovers over …
Browse files Browse the repository at this point in the history
…them.

PiperOrigin-RevId: 374767883
  • Loading branch information
sayris authored and copybara-github committed May 20, 2021
1 parent 4bb5eea commit ccce99c
Show file tree
Hide file tree
Showing 2 changed files with 78 additions and 37 deletions.
59 changes: 33 additions & 26 deletions packages/mdc-tooltip/foundation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -112,9 +112,9 @@ export class MDCTooltipFoundation extends MDCFoundation<MDCTooltipAdapter> {
private readonly anchorBlurHandler: SpecificEventListener<'blur'>;
private readonly documentClickHandler: SpecificEventListener<'click'>;
private readonly documentKeydownHandler: SpecificEventListener<'keydown'>;
private readonly richTooltipMouseEnterHandler:
private readonly tooltipMouseEnterHandler:
SpecificEventListener<'mouseenter'>;
private readonly richTooltipMouseLeaveHandler:
private readonly tooltipMouseLeaveHandler:
SpecificEventListener<'mouseleave'>;
private readonly richTooltipFocusOutHandler:
SpecificEventListener<'focusout'>;
Expand All @@ -140,12 +140,12 @@ export class MDCTooltipFoundation extends MDCFoundation<MDCTooltipAdapter> {
this.handleKeydown(evt);
};

this.richTooltipMouseEnterHandler = () => {
this.handleRichTooltipMouseEnter();
this.tooltipMouseEnterHandler = () => {
this.handleTooltipMouseEnter();
};

this.richTooltipMouseLeaveHandler = () => {
this.handleRichTooltipMouseLeave();
this.tooltipMouseLeaveHandler = () => {
this.handleTooltipMouseLeave();
};

this.richTooltipFocusOutHandler = (evt) => {
Expand Down Expand Up @@ -308,11 +308,11 @@ export class MDCTooltipFoundation extends MDCFoundation<MDCTooltipAdapter> {
this.hide();
}

private handleRichTooltipMouseEnter() {
private handleTooltipMouseEnter() {
this.show();
}

private handleRichTooltipMouseLeave() {
private handleTooltipMouseLeave() {
this.clearShowTimeout();
this.hideTimeout = setTimeout(() => {
this.hide();
Expand Down Expand Up @@ -358,19 +358,22 @@ export class MDCTooltipFoundation extends MDCFoundation<MDCTooltipAdapter> {
if (!showTooltipOptions.hideFromScreenreader) {
this.adapter.setAttribute('aria-hidden', 'false');
}

if (this.richTooltip) {
if (this.interactiveTooltip) {
this.adapter.setAnchorAttribute('aria-expanded', 'true');
}
this.adapter.registerEventHandler(
'focusout', this.richTooltipFocusOutHandler);
if (!this.persistentTooltip) {
this.adapter.registerEventHandler(
'mouseenter', this.richTooltipMouseEnterHandler);
this.adapter.registerEventHandler(
'mouseleave', this.richTooltipMouseLeaveHandler);
}
}

if (!this.persistentTooltip) {
this.adapter.registerEventHandler(
'mouseenter', this.tooltipMouseEnterHandler);
this.adapter.registerEventHandler(
'mouseleave', this.tooltipMouseLeaveHandler);
}

this.adapter.removeClass(HIDE);
this.adapter.addClass(SHOWING);
if (this.isTooltipMultiline() && !this.richTooltip) {
Expand Down Expand Up @@ -420,13 +423,15 @@ export class MDCTooltipFoundation extends MDCFoundation<MDCTooltipAdapter> {
if (this.interactiveTooltip) {
this.adapter.setAnchorAttribute('aria-expanded', 'false');
}
if (!this.persistentTooltip) {
this.adapter.deregisterEventHandler(
'mouseenter', this.richTooltipMouseEnterHandler);
this.adapter.deregisterEventHandler(
'mouseleave', this.richTooltipMouseLeaveHandler);
}
}

if (!this.persistentTooltip) {
this.adapter.deregisterEventHandler(
'mouseenter', this.tooltipMouseEnterHandler);
this.adapter.deregisterEventHandler(
'mouseleave', this.tooltipMouseLeaveHandler);
}

this.clearAllAnimationClasses();
this.adapter.addClass(HIDE);
this.adapter.addClass(HIDE_TRANSITION);
Expand Down Expand Up @@ -1395,13 +1400,15 @@ export class MDCTooltipFoundation extends MDCFoundation<MDCTooltipAdapter> {
if (this.richTooltip) {
this.adapter.deregisterEventHandler(
'focusout', this.richTooltipFocusOutHandler);
if (!this.persistentTooltip) {
this.adapter.deregisterEventHandler(
'mouseenter', this.richTooltipMouseEnterHandler);
this.adapter.deregisterEventHandler(
'mouseleave', this.richTooltipMouseLeaveHandler);
}
}

if (!this.persistentTooltip) {
this.adapter.deregisterEventHandler(
'mouseenter', this.tooltipMouseEnterHandler);
this.adapter.deregisterEventHandler(
'mouseleave', this.tooltipMouseLeaveHandler);
}

this.adapter.deregisterAnchorEventHandler('blur', this.anchorBlurHandler);

this.adapter.deregisterDocumentEventHandler(
Expand Down
56 changes: 45 additions & 11 deletions packages/mdc-tooltip/test/foundation.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1097,37 +1097,71 @@ describe('MDCTooltipFoundation', () => {
expectTooltipToHaveBeenHidden(foundation, mockAdapter);
});

it(`#handleTooltipMouseEnter shows plain tooltips immediately`, () => {
const {foundation, mockAdapter} = setUpFoundationTest(MDCTooltipFoundation);

(foundation as any).handleTooltipMouseEnter();
expectTooltipToHaveBeenShown(foundation, mockAdapter);
});

it(`#handleTooltipMouseLeave hides plain tooltips after a ${
numbers.HIDE_DELAY_MS}ms delay`,
() => {
const {foundation, mockAdapter} = setUpFoundationTest(MDCTooltipFoundation);

foundation.show();
(foundation as any).handleTooltipMouseLeave();
expect((foundation as any).hideTimeout).not.toEqual(null);
jasmine.clock().tick(numbers.HIDE_DELAY_MS);

expectTooltipToHaveBeenHidden(foundation, mockAdapter);
});

it('#handleTooltipMouseLeave clears any pending showTimeout for plain tooltips', () => {
const {foundation, mockAdapter} = setUpFoundationTest(MDCTooltipFoundation);

it(`#handleRichTooltipMouseEnter shows the tooltip immediately`, () => {
foundation.handleAnchorMouseEnter();
expect((foundation as any).showTimeout).not.toEqual(null);
(foundation as any).handleTooltipMouseLeave();

expect((foundation as any).showTimeout).toEqual(null);
jasmine.clock().tick(numbers.SHOW_DELAY_MS);
expect(mockAdapter.setAttribute)
.not.toHaveBeenCalledWith('aria-hidden', 'false');
expect(mockAdapter.removeClass).not.toHaveBeenCalledWith(CssClasses.HIDE);
expect(mockAdapter.addClass).not.toHaveBeenCalledWith(CssClasses.SHOWING);
});

it(`#handleTooltipMouseEnter shows rich tooltips immediately`, () => {
const {foundation, mockAdapter} =
setUpFoundationTestForRichTooltip(MDCTooltipFoundation);

(foundation as any).handleRichTooltipMouseEnter();
(foundation as any).handleTooltipMouseEnter();

expectTooltipToHaveBeenShown(foundation, mockAdapter);
});

it(`#handleRichTooltipMouseLeave hides the tooltip after a ${
it(`#handleTooltipMouseLeave hides rich tooltips after a ${
numbers.HIDE_DELAY_MS}ms delay`,
() => {
const {foundation, mockAdapter} =
setUpFoundationTestForRichTooltip(MDCTooltipFoundation);

foundation.show();
(foundation as any).handleRichTooltipMouseLeave();
(foundation as any).handleTooltipMouseLeave();
expect((foundation as any).hideTimeout).not.toEqual(null);
jasmine.clock().tick(numbers.HIDE_DELAY_MS);

expectTooltipToHaveBeenHidden(foundation, mockAdapter);
});

it('#handleRichTooltipMouseLeave clears any pending showTimeout', () => {
it('#handleTooltipMouseLeave clears any pending showTimeout for rich tooltips', () => {
const {foundation, mockAdapter} =
setUpFoundationTestForRichTooltip(MDCTooltipFoundation);

foundation.handleAnchorMouseEnter();
expect((foundation as any).showTimeout).not.toEqual(null);
(foundation as any).handleRichTooltipMouseLeave();
(foundation as any).handleTooltipMouseLeave();

expect((foundation as any).showTimeout).toEqual(null);
jasmine.clock().tick(numbers.SHOW_DELAY_MS);
Expand Down Expand Up @@ -1261,13 +1295,13 @@ describe('MDCTooltipFoundation', () => {
expect(mockAdapter.addClass).not.toHaveBeenCalledWith(CssClasses.SHOWING);
});

it('#handleRichTooltipMouseEnter keeps tooltip visible', () => {
it('#handleTooltipMouseEnter keeps tooltip visible', () => {
const {foundation, mockAdapter} =
setUpFoundationTestForRichTooltip(MDCTooltipFoundation);

foundation.handleAnchorMouseLeave();
expect((foundation as any).hideTimeout).not.toEqual(null);
(foundation as any).handleRichTooltipMouseEnter();
(foundation as any).handleTooltipMouseEnter();

expect((foundation as any).hideTimeout).toEqual(null);
expect(mockAdapter.setAttribute)
Expand Down Expand Up @@ -2014,11 +2048,11 @@ describe('MDCTooltipFoundation', () => {
foundation.destroy();

expect(mockAdapter.deregisterEventHandler)
.not.toHaveBeenCalledWith('focusout', jasmine.any(Function));
.toHaveBeenCalledWith('mouseenter', jasmine.any(Function));
expect(mockAdapter.deregisterEventHandler)
.not.toHaveBeenCalledWith('mouseenter', jasmine.any(Function));
.toHaveBeenCalledWith('mouseleave', jasmine.any(Function));
expect(mockAdapter.deregisterEventHandler)
.not.toHaveBeenCalledWith('mouseleave', jasmine.any(Function));
.not.toHaveBeenCalledWith('focusout', jasmine.any(Function));
expect(mockAdapter.deregisterDocumentEventHandler)
.toHaveBeenCalledWith('click', jasmine.any(Function));
expect(mockAdapter.deregisterDocumentEventHandler)
Expand Down

0 comments on commit ccce99c

Please sign in to comment.