Skip to content

Commit

Permalink
feat(tooltip): Set up rich tooltip to persist if mouse leaves anchor …
Browse files Browse the repository at this point in the history
…and enters rich tooltip.

BREAKING CHANGE:
  Added adapter methods:
  - setAnchorAttribute(attr: string, value: string): void;
  - registerEventHandler<K extends EventType>(
        evtType: K, handler: SpecificEventListener<K>): void;
  - deregisterEventHandler<K extends EventType>(
        evtType: K, handler: SpecificEventListener<K>): void;
Rich tooltips are currently in development and is not yet ready for use.

PiperOrigin-RevId: 343894231
  • Loading branch information
material-web-copybara authored and Copybara-Service committed Nov 23, 2020
1 parent 7b0e2b3 commit c927a5d
Show file tree
Hide file tree
Showing 6 changed files with 377 additions and 164 deletions.
17 changes: 17 additions & 0 deletions packages/mdc-tooltip/adapter.ts
Expand Up @@ -88,11 +88,28 @@ export interface MDCTooltipAdapter {
*/
getAnchorAttribute(attr: string): string|null;

/**
* Sets an attribute on the anchor element.
*/
setAnchorAttribute(attr: string, value: string): void;

/**
* @return true if the text direction is right-to-left.
*/
isRTL(): boolean;

/**
* Registers an event listener to the root element.
*/
registerEventHandler<K extends EventType>(
evtType: K, handler: SpecificEventListener<K>): void;

/**
* Deregisters an event listener to the root element.
*/
deregisterEventHandler<K extends EventType>(
evtType: K, handler: SpecificEventListener<K>): void;

/**
* Registers an event listener to the document body.
*/
Expand Down
13 changes: 13 additions & 0 deletions packages/mdc-tooltip/component.ts
Expand Up @@ -134,7 +134,20 @@ export class MDCTooltip extends MDCComponent<MDCTooltipFoundation> {
getAnchorAttribute: (attr) => {
return this.anchorElem ? this.anchorElem.getAttribute(attr) : null;
},
setAnchorAttribute: (attr, value) => {
this.anchorElem?.setAttribute(attr, value);
},
isRTL: () => getComputedStyle(this.root).direction === 'rtl',
registerEventHandler: (evt, handler) => {
if (this.root instanceof HTMLElement) {
this.root.addEventListener(evt, handler);
}
},
deregisterEventHandler: (evt, handler) => {
if (this.root instanceof HTMLElement) {
this.root.removeEventListener(evt, handler);
}
},
registerDocumentEventHandler: (evt, handler) => {
document.body.addEventListener(evt, handler);
},
Expand Down
1 change: 1 addition & 0 deletions packages/mdc-tooltip/constants.ts
Expand Up @@ -22,6 +22,7 @@
*/

enum CssClasses {
RICH = 'mdc-tooltip--rich',
SHOWN = 'mdc-tooltip--shown',
SHOWING = 'mdc-tooltip--showing',
SHOWING_TRANSITION = 'mdc-tooltip--showing-transition',
Expand Down
36 changes: 35 additions & 1 deletion packages/mdc-tooltip/foundation.ts
Expand Up @@ -30,6 +30,7 @@ import {AnchorBoundaryType, CssClasses, numbers, XPosition, YPosition} from './c
import {ShowTooltipOptions} from './types';

const {
RICH,
SHOWN,
SHOWING,
SHOWING_TRANSITION,
Expand Down Expand Up @@ -57,7 +58,10 @@ export class MDCTooltipFoundation extends MDCFoundation<MDCTooltipAdapter> {
getAnchorBoundingRect: () =>
({top: 0, right: 0, bottom: 0, left: 0, width: 0, height: 0}),
getAnchorAttribute: () => null,
setAnchorAttribute: () => null,
isRTL: () => false,
registerEventHandler: () => undefined,
deregisterEventHandler: () => undefined,
registerDocumentEventHandler: () => undefined,
deregisterDocumentEventHandler: () => undefined,
registerWindowEventHandler: () => undefined,
Expand All @@ -66,6 +70,7 @@ export class MDCTooltipFoundation extends MDCFoundation<MDCTooltipAdapter> {
};
}

private isRich!: boolean; // assigned in init()
private isShown = false;
private anchorGap = numbers.BOUNDED_ANCHOR_GAP;
private xTooltipPos = XPosition.DETECTED;
Expand All @@ -83,6 +88,8 @@ export class MDCTooltipFoundation extends MDCFoundation<MDCTooltipAdapter> {
private readonly animFrame: AnimationFrame;
private readonly documentClickHandler: SpecificEventListener<'click'>;
private readonly documentKeydownHandler: SpecificEventListener<'keydown'>;
private readonly richTooltipMouseEnterHandler:
SpecificEventListener<'mouseenter'>;
private readonly windowScrollHandler: SpecificEventListener<'scroll'>;
private readonly windowResizeHandler: SpecificEventListener<'resize'>;

Expand All @@ -98,6 +105,10 @@ export class MDCTooltipFoundation extends MDCFoundation<MDCTooltipAdapter> {
this.handleKeydown(evt);
};

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

this.windowScrollHandler = () => {
this.handleWindowChangeEvent();
};
Expand All @@ -107,6 +118,10 @@ export class MDCTooltipFoundation extends MDCFoundation<MDCTooltipAdapter> {
};
}

init() {
this.isRich = this.adapter.hasClass(RICH);
}

handleAnchorMouseEnter() {
if (this.isShown) {
// Covers the instance where a user hovers over the anchor to reveal the
Expand Down Expand Up @@ -155,6 +170,10 @@ export class MDCTooltipFoundation extends MDCFoundation<MDCTooltipAdapter> {
}
}

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

/**
* On window resize or scroll, check the anchor position and size and
* repostion tooltip if necessary.
Expand All @@ -181,9 +200,14 @@ export class MDCTooltipFoundation extends MDCFoundation<MDCTooltipAdapter> {
if (!showTooltipOptions.hideFromScreenreader) {
this.adapter.setAttribute('aria-hidden', 'false');
}
if (this.isRich) {
this.adapter.setAnchorAttribute('aria-expanded', 'true');
this.adapter.registerEventHandler(
'mouseenter', this.richTooltipMouseEnterHandler);
}
this.adapter.removeClass(HIDE);
this.adapter.addClass(SHOWING);
if (this.isTooltipMultiline()) {
if (this.isTooltipMultiline() && !this.isRich) {
this.adapter.addClass(MULTILINE_TOOLTIP);
}
this.anchorRect = this.adapter.getAnchorBoundingRect();
Expand Down Expand Up @@ -218,6 +242,11 @@ export class MDCTooltipFoundation extends MDCFoundation<MDCTooltipAdapter> {

this.isShown = false;
this.adapter.setAttribute('aria-hidden', 'true');
if (this.isRich) {
this.adapter.setAnchorAttribute('aria-expanded', 'false');
this.adapter.deregisterEventHandler(
'mouseenter', this.richTooltipMouseEnterHandler);
}
this.clearAllAnimationClasses();
this.adapter.addClass(HIDE);
this.adapter.addClass(HIDE_TRANSITION);
Expand Down Expand Up @@ -543,6 +572,11 @@ export class MDCTooltipFoundation extends MDCFoundation<MDCTooltipAdapter> {
this.adapter.removeClass(HIDE);
this.adapter.removeClass(HIDE_TRANSITION);

if (this.isRich) {
this.adapter.deregisterEventHandler(
'mouseenter', this.richTooltipMouseEnterHandler);
}

this.adapter.deregisterDocumentEventHandler(
'click', this.documentClickHandler);
this.adapter.deregisterDocumentEventHandler(
Expand Down

0 comments on commit c927a5d

Please sign in to comment.