Skip to content

Commit 52582f4

Browse files
andrewseguinhansl
authored andcommitted
feat(tooltip): add tooltip animations (#1644)
1 parent ad3100e commit 52582f4

File tree

5 files changed

+308
-130
lines changed

5 files changed

+308
-130
lines changed
Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,16 @@
11
<div class="demo-tooltip">
22
<h1>Tooltip Demo</h1>
3+
34
<p class="centered">
4-
<button
5+
<button #tooltip="mdTooltip"
56
md-raised-button
67
color="primary"
7-
md-tooltip="to see a tooltip"
8+
[md-tooltip]="message"
89
[tooltip-position]="position">
9-
Mouse over this link
10+
Mouse over to see the tooltip
1011
</button>
1112
</p>
13+
1214
<p>
1315
<md-radio-group [(ngModel)]="position">
1416
<md-radio-button value="below">Below</md-radio-button>
@@ -17,4 +19,20 @@ <h1>Tooltip Demo</h1>
1719
<md-radio-button value="after">After</md-radio-button>
1820
</md-radio-group>
1921
</p>
22+
23+
<p>
24+
<strong>Message: </strong>
25+
<md-input type="text" [(ngModel)]="message"></md-input>
26+
</p>
27+
28+
<strong>Mouse over to</strong>
29+
<button md-raised-button color="primary" (mouseenter)="tooltip.show()">
30+
Show tooltip
31+
</button>
32+
<button md-raised-button color="primary" (mouseenter)="tooltip.hide(0)">
33+
Hide tooltip
34+
</button>
35+
<button md-raised-button color="primary" (mouseenter)="tooltip.toggle()">
36+
Toggle tooltip
37+
</button>
2038
</div>

src/demo-app/tooltip/tooltip-demo.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,4 +10,5 @@ import {TooltipPosition} from '@angular/material';
1010
})
1111
export class TooltipDemo {
1212
position: TooltipPosition = 'below';
13+
message: string = 'Here is the tooltip';
1314
}

src/lib/tooltip/tooltip.html

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
<div class="md-tooltip"
2+
[style.transform-origin]="_transformOrigin"
3+
[@state]="_visibility"
4+
(@state.done)="this._afterVisibilityAnimation($event)">
5+
{{message}}
6+
</div>

src/lib/tooltip/tooltip.spec.ts

Lines changed: 79 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,18 @@
1-
import {async, ComponentFixture, TestBed} from '@angular/core/testing';
1+
import {
2+
async, ComponentFixture, TestBed, tick, fakeAsync,
3+
flushMicrotasks
4+
} from '@angular/core/testing';
25
import {Component, DebugElement} from '@angular/core';
36
import {By} from '@angular/platform-browser';
4-
import {TooltipPosition, MdTooltip} from './tooltip';
7+
import {TooltipPosition, MdTooltip, TOOLTIP_HIDE_DELAY, MdTooltipModule} from './tooltip';
58
import {OverlayContainer} from '../core';
6-
import {MdTooltipModule} from './tooltip';
79

10+
const initialTooltipMessage = 'initial tooltip message';
811

912
describe('MdTooltip', () => {
1013
let overlayContainerElement: HTMLElement;
1114

15+
1216
beforeEach(async(() => {
1317
TestBed.configureTestingModule({
1418
imports: [MdTooltipModule.forRoot()],
@@ -38,22 +42,83 @@ describe('MdTooltip', () => {
3842
tooltipDirective = buttonDebugElement.injector.get(MdTooltip);
3943
});
4044

41-
it('should show/hide on mouse enter/leave', () => {
42-
expect(tooltipDirective.visible).toBeFalsy();
45+
it('should show and hide the tooltip', fakeAsync(() => {
46+
expect(tooltipDirective._tooltipInstance).toBeUndefined();
4347

44-
tooltipDirective._handleMouseEnter(null);
45-
expect(tooltipDirective.visible).toBeTruthy();
48+
tooltipDirective.show();
49+
expect(tooltipDirective._isTooltipVisible()).toBe(true);
4650

4751
fixture.detectChanges();
48-
expect(overlayContainerElement.textContent).toBe('some message');
52+
expect(overlayContainerElement.textContent).toContain(initialTooltipMessage);
4953

50-
tooltipDirective._handleMouseLeave(null);
51-
expect(overlayContainerElement.textContent).toBe('');
54+
// After hide called, a timeout delay is created that will to hide the tooltip.
55+
tooltipDirective.hide();
56+
expect(tooltipDirective._isTooltipVisible()).toBe(true);
57+
58+
// After the tooltip delay elapses, expect that the tooltip is not visible.
59+
tick(TOOLTIP_HIDE_DELAY);
60+
fixture.detectChanges();
61+
expect(tooltipDirective._isTooltipVisible()).toBe(false);
62+
63+
// On animation complete, should expect that the tooltip has been detached.
64+
flushMicrotasks();
65+
expect(tooltipDirective._tooltipInstance).toBeNull();
66+
}));
67+
68+
it('should not follow through with hide if show is called after', fakeAsync(() => {
69+
tooltipDirective.show();
70+
expect(tooltipDirective._isTooltipVisible()).toBe(true);
71+
72+
// After hide called, a timeout delay is created that will to hide the tooltip.
73+
tooltipDirective.hide();
74+
expect(tooltipDirective._isTooltipVisible()).toBe(true);
75+
76+
// Before delay time has passed, call show which should cancel intent to hide tooltip.
77+
tooltipDirective.show();
78+
tick(TOOLTIP_HIDE_DELAY);
79+
expect(tooltipDirective._isTooltipVisible()).toBe(true);
80+
}));
81+
82+
it('should remove the tooltip when changing position', () => {
83+
const initialPosition: TooltipPosition = 'below';
84+
const changedPosition: TooltipPosition = 'above';
85+
86+
expect(tooltipDirective._tooltipInstance).toBeUndefined();
87+
88+
tooltipDirective.position = initialPosition;
89+
tooltipDirective.show();
90+
expect(tooltipDirective._tooltipInstance).toBeDefined();
91+
92+
// Same position value should not remove the tooltip
93+
tooltipDirective.position = initialPosition;
94+
expect(tooltipDirective._tooltipInstance).toBeDefined();
95+
96+
// Different position value should destroy the tooltip
97+
tooltipDirective.position = changedPosition;
98+
expect(tooltipDirective._tooltipInstance).toBeNull();
99+
expect(tooltipDirective._overlayRef).toBeNull();
100+
});
101+
102+
it('should be able to modify the tooltip message', () => {
103+
expect(tooltipDirective._tooltipInstance).toBeUndefined();
104+
105+
tooltipDirective.show();
106+
expect(tooltipDirective._tooltipInstance._visibility).toBe('visible');
107+
108+
fixture.detectChanges();
109+
expect(overlayContainerElement.textContent).toContain(initialTooltipMessage);
110+
111+
const newMessage = 'new tooltip message';
112+
tooltipDirective.message = newMessage;
113+
114+
fixture.detectChanges();
115+
expect(overlayContainerElement.textContent).toContain(newMessage);
52116
});
53117

54118
it('should be removed after parent destroyed', () => {
55-
tooltipDirective._handleMouseEnter(null);
56-
expect(tooltipDirective.visible).toBeTruthy();
119+
tooltipDirective.show();
120+
expect(tooltipDirective._isTooltipVisible()).toBe(true);
121+
57122
fixture.destroy();
58123
expect(overlayContainerElement.childNodes.length).toBe(0);
59124
expect(overlayContainerElement.textContent).toBe('');
@@ -63,8 +128,9 @@ describe('MdTooltip', () => {
63128

64129
@Component({
65130
selector: 'app',
66-
template: `<button md-tooltip="some message" [tooltip-position]="position">Button</button>`
131+
template: `<button [md-tooltip]="message" [tooltip-position]="position">Button</button>`
67132
})
68133
class BasicTooltipDemo {
69134
position: TooltipPosition = 'below';
135+
message: string = initialTooltipMessage;
70136
}

0 commit comments

Comments
 (0)