Skip to content

Commit 233fb98

Browse files
committed
fixup! Revert "Revert "feat(material/tooltip): add option to open tooltip at mouse position (#25202)" (#25430)"
1 parent 6231c16 commit 233fb98

File tree

5 files changed

+59
-65
lines changed

5 files changed

+59
-65
lines changed

src/material/legacy-tooltip/tooltip.spec.ts

Lines changed: 14 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -237,7 +237,7 @@ describe('MatTooltip', () => {
237237
TestBed.resetTestingModule()
238238
.configureTestingModule({
239239
imports: [MatLegacyTooltipModule, OverlayModule],
240-
declarations: [WideTooltipDemo]
240+
declarations: [WideTooltipDemo],
241241
})
242242
.compileComponents();
243243

@@ -254,8 +254,12 @@ describe('MatTooltip', () => {
254254
tick();
255255
expect(tooltipDirective._isTooltipVisible()).toBe(true);
256256

257-
expect(tooltipDirective._overlayRef!.overlayElement.offsetLeft).toBeGreaterThan(triggerRect.left + 200);
258-
expect(tooltipDirective._overlayRef!.overlayElement.offsetLeft).toBeLessThan(triggerRect.left + 300);
257+
expect(tooltipDirective._overlayRef!.overlayElement.offsetLeft).toBeGreaterThan(
258+
triggerRect.left + 200,
259+
);
260+
expect(tooltipDirective._overlayRef!.overlayElement.offsetLeft).toBeLessThan(
261+
triggerRect.left + 300,
262+
);
259263
expect(tooltipDirective._overlayRef!.overlayElement.offsetTop).toBe(triggerRect.bottom);
260264
}));
261265

@@ -1227,10 +1231,7 @@ describe('MatTooltip', () => {
12271231
fixture.detectChanges();
12281232
const button: HTMLButtonElement = fixture.nativeElement.querySelector('button');
12291233

1230-
const triggerRect = button.getBoundingClientRect();
1231-
const offsetX = triggerRect.right - 10;
1232-
const offsetY = triggerRect.top + 10;
1233-
dispatchTouchEvent(button, 'touchstart', offsetX, offsetY, offsetX, offsetY);
1234+
dispatchFakeEvent(button, 'touchstart');
12341235
fixture.detectChanges();
12351236
tick(250); // Halfway through the delay.
12361237

@@ -1249,10 +1250,7 @@ describe('MatTooltip', () => {
12491250
fixture.detectChanges();
12501251
const button: HTMLButtonElement = fixture.nativeElement.querySelector('button');
12511252

1252-
const triggerRect = button.getBoundingClientRect();
1253-
const offsetX = triggerRect.right - 10;
1254-
const offsetY = triggerRect.top + 10;
1255-
dispatchTouchEvent(button, 'touchstart', offsetX, offsetY, offsetX, offsetY);
1253+
dispatchFakeEvent(button, 'touchstart');
12561254
fixture.detectChanges();
12571255
tick(500); // Finish the delay.
12581256
fixture.detectChanges();
@@ -1265,10 +1263,7 @@ describe('MatTooltip', () => {
12651263
const fixture = TestBed.createComponent(BasicTooltipDemo);
12661264
fixture.detectChanges();
12671265
const button: HTMLButtonElement = fixture.nativeElement.querySelector('button');
1268-
const triggerRect = button.getBoundingClientRect();
1269-
const offsetX = triggerRect.right - 10;
1270-
const offsetY = triggerRect.top + 10;
1271-
const event = dispatchTouchEvent(button, 'touchstart', offsetX, offsetY, offsetX, offsetY);
1266+
const event = dispatchFakeEvent(button, 'touchstart');
12721267
fixture.detectChanges();
12731268

12741269
expect(event.defaultPrevented).toBe(false);
@@ -1279,10 +1274,7 @@ describe('MatTooltip', () => {
12791274
fixture.detectChanges();
12801275
const button: HTMLButtonElement = fixture.nativeElement.querySelector('button');
12811276

1282-
const triggerRect = button.getBoundingClientRect();
1283-
const offsetX = triggerRect.right - 10;
1284-
const offsetY = triggerRect.top + 10;
1285-
dispatchTouchEvent(button, 'touchstart', offsetX, offsetY, offsetX, offsetY);
1277+
dispatchFakeEvent(button, 'touchstart');
12861278
fixture.detectChanges();
12871279
tick(500); // Finish the open delay.
12881280
fixture.detectChanges();
@@ -1306,10 +1298,7 @@ describe('MatTooltip', () => {
13061298
fixture.detectChanges();
13071299
const button: HTMLButtonElement = fixture.nativeElement.querySelector('button');
13081300

1309-
const triggerRect = button.getBoundingClientRect();
1310-
const offsetX = triggerRect.right - 10;
1311-
const offsetY = triggerRect.top + 10;
1312-
dispatchTouchEvent(button, 'touchstart', offsetX, offsetY, offsetX, offsetY);
1301+
dispatchFakeEvent(button, 'touchstart');
13131302
fixture.detectChanges();
13141303
tick(500); // Finish the open delay.
13151304
fixture.detectChanges();
@@ -1474,16 +1463,16 @@ describe('MatTooltip', () => {
14741463
const fixture = TestBed.createComponent(BasicTooltipDemo);
14751464
fixture.detectChanges();
14761465
const button: HTMLButtonElement = fixture.nativeElement.querySelector('button');
1477-
const triggerRect = button.getBoundingClientRect();
14781466

1479-
dispatchMouseEvent(button, 'mouseenter', triggerRect.right - 10, triggerRect.top + 10);
1467+
dispatchFakeEvent(button, 'mouseenter');
14801468
fixture.detectChanges();
14811469
tick(500); // Finish the open delay.
14821470
fixture.detectChanges();
14831471
finishCurrentTooltipAnimation(overlayContainerElement, true);
14841472
assertTooltipInstance(fixture.componentInstance.tooltip, true);
14851473

14861474
// Simulate the pointer over the trigger.
1475+
const triggerRect = button.getBoundingClientRect();
14871476
const wheelEvent = createFakeEvent('wheel');
14881477
Object.defineProperties(wheelEvent, {
14891478
clientX: {get: () => triggerRect.left + 1},

src/material/tooltip/tooltip.spec.ts

Lines changed: 18 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -239,7 +239,7 @@ describe('MDC-based MatTooltip', () => {
239239
TestBed.resetTestingModule()
240240
.configureTestingModule({
241241
imports: [MatTooltipModule, OverlayModule],
242-
declarations: [WideTooltipDemo]
242+
declarations: [WideTooltipDemo],
243243
})
244244
.compileComponents();
245245

@@ -256,8 +256,12 @@ describe('MDC-based MatTooltip', () => {
256256
tick();
257257
expect(tooltipDirective._isTooltipVisible()).toBe(true);
258258

259-
expect(tooltipDirective._overlayRef!.overlayElement.offsetLeft).toBeLessThan(triggerRect.right - 250);
260-
expect(tooltipDirective._overlayRef!.overlayElement.offsetTop).toBeGreaterThanOrEqual(triggerRect.bottom);
259+
expect(tooltipDirective._overlayRef!.overlayElement.offsetLeft).toBeLessThan(
260+
triggerRect.right - 250,
261+
);
262+
expect(tooltipDirective._overlayRef!.overlayElement.offsetTop).toBeGreaterThanOrEqual(
263+
triggerRect.bottom,
264+
);
261265
}));
262266

263267
it('should be able to override the default positionAtOrigin', fakeAsync(() => {
@@ -287,7 +291,9 @@ describe('MDC-based MatTooltip', () => {
287291
tick();
288292
expect(tooltipDirective._isTooltipVisible()).toBe(true);
289293

290-
expect(tooltipDirective._overlayRef!.overlayElement.offsetLeft).toBe(triggerRect.right - 100 - 20);
294+
expect(tooltipDirective._overlayRef!.overlayElement.offsetLeft).toBe(
295+
triggerRect.right - 100 - 20,
296+
);
291297
expect(tooltipDirective._overlayRef!.overlayElement.offsetTop).toBe(triggerRect.top + 100);
292298
}));
293299

@@ -1258,10 +1264,7 @@ describe('MDC-based MatTooltip', () => {
12581264
fixture.detectChanges();
12591265
const button: HTMLButtonElement = fixture.nativeElement.querySelector('button');
12601266

1261-
const triggerRect = button.getBoundingClientRect();
1262-
const offsetX = triggerRect.right - 10;
1263-
const offsetY = triggerRect.top + 10;
1264-
dispatchTouchEvent(button, 'touchstart', offsetX, offsetY, offsetX, offsetY);
1267+
dispatchFakeEvent(button, 'touchstart');
12651268
fixture.detectChanges();
12661269
tick(250); // Halfway through the delay.
12671270

@@ -1280,10 +1283,7 @@ describe('MDC-based MatTooltip', () => {
12801283
fixture.detectChanges();
12811284
const button: HTMLButtonElement = fixture.nativeElement.querySelector('button');
12821285

1283-
const triggerRect = button.getBoundingClientRect();
1284-
const offsetX = triggerRect.right - 10;
1285-
const offsetY = triggerRect.top + 10;
1286-
dispatchTouchEvent(button, 'touchstart', offsetX, offsetY, offsetX, offsetY);
1286+
dispatchFakeEvent(button, 'touchstart');
12871287
fixture.detectChanges();
12881288
tick(500); // Finish the delay.
12891289
fixture.detectChanges();
@@ -1296,10 +1296,7 @@ describe('MDC-based MatTooltip', () => {
12961296
const fixture = TestBed.createComponent(BasicTooltipDemo);
12971297
fixture.detectChanges();
12981298
const button: HTMLButtonElement = fixture.nativeElement.querySelector('button');
1299-
const triggerRect = button.getBoundingClientRect();
1300-
const offsetX = triggerRect.right - 10;
1301-
const offsetY = triggerRect.top + 10;
1302-
const event = dispatchTouchEvent(button, 'touchstart', offsetX, offsetY, offsetX, offsetY);
1299+
const event = dispatchFakeEvent(button, 'touchstart');
13031300
fixture.detectChanges();
13041301

13051302
expect(event.defaultPrevented).toBe(false);
@@ -1310,10 +1307,7 @@ describe('MDC-based MatTooltip', () => {
13101307
fixture.detectChanges();
13111308
const button: HTMLButtonElement = fixture.nativeElement.querySelector('button');
13121309

1313-
const triggerRect = button.getBoundingClientRect();
1314-
const offsetX = triggerRect.right - 10;
1315-
const offsetY = triggerRect.top + 10;
1316-
dispatchTouchEvent(button, 'touchstart', offsetX, offsetY, offsetX, offsetY);
1310+
dispatchFakeEvent(button, 'touchstart');
13171311
fixture.detectChanges();
13181312
tick(500); // Finish the open delay.
13191313
fixture.detectChanges();
@@ -1337,10 +1331,7 @@ describe('MDC-based MatTooltip', () => {
13371331
fixture.detectChanges();
13381332
const button: HTMLButtonElement = fixture.nativeElement.querySelector('button');
13391333

1340-
const triggerRect = button.getBoundingClientRect();
1341-
const offsetX = triggerRect.right - 10;
1342-
const offsetY = triggerRect.top + 10;
1343-
dispatchTouchEvent(button, 'touchstart', offsetX, offsetY, offsetX, offsetY);
1334+
dispatchFakeEvent(button, 'touchstart');
13441335
fixture.detectChanges();
13451336
tick(500); // Finish the open delay.
13461337
fixture.detectChanges();
@@ -1472,9 +1463,8 @@ describe('MDC-based MatTooltip', () => {
14721463
const fixture = TestBed.createComponent(BasicTooltipDemo);
14731464
fixture.detectChanges();
14741465
const button: HTMLButtonElement = fixture.nativeElement.querySelector('button');
1475-
const triggerRect = button.getBoundingClientRect();
14761466

1477-
dispatchMouseEvent(button, 'mouseenter', triggerRect.right - 10, triggerRect.top + 10);
1467+
dispatchFakeEvent(button, 'mouseenter');
14781468
fixture.detectChanges();
14791469
tick(500); // Finish the open delay.
14801470
fixture.detectChanges();
@@ -1506,16 +1496,16 @@ describe('MDC-based MatTooltip', () => {
15061496
const fixture = TestBed.createComponent(BasicTooltipDemo);
15071497
fixture.detectChanges();
15081498
const button: HTMLButtonElement = fixture.nativeElement.querySelector('button');
1509-
const triggerRect = button.getBoundingClientRect();
15101499

1511-
dispatchMouseEvent(button, 'mouseenter', triggerRect.right - 10, triggerRect.top + 10);
1500+
dispatchFakeEvent(button, 'mouseenter');
15121501
fixture.detectChanges();
15131502
tick(500); // Finish the open delay.
15141503
fixture.detectChanges();
15151504
finishCurrentTooltipAnimation(overlayContainerElement, true);
15161505
assertTooltipInstance(fixture.componentInstance.tooltip, true);
15171506

15181507
// Simulate the pointer over the trigger.
1508+
const triggerRect = button.getBoundingClientRect();
15191509
const wheelEvent = createFakeEvent('wheel');
15201510
Object.defineProperties(wheelEvent, {
15211511
clientX: {get: () => triggerRect.left + 1},

src/material/tooltip/tooltip.ts

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -407,7 +407,7 @@ export abstract class _MatTooltipBase<T extends _TooltipComponentBase>
407407
}
408408

409409
/** Shows the tooltip after the delay in ms, defaults to tooltip-delay-show or 0ms if no input */
410-
show(delay: number = this.showDelay, origin?: { x: number, y: number }): void {
410+
show(delay: number = this.showDelay, origin?: {x: number; y: number}): void {
411411
if (
412412
this.disabled ||
413413
!this.message ||
@@ -442,7 +442,7 @@ export abstract class _MatTooltipBase<T extends _TooltipComponentBase>
442442
}
443443

444444
/** Shows/hides the tooltip */
445-
toggle(origin?: { x: number; y: number; }): void {
445+
toggle(origin?: {x: number; y: number}): void {
446446
this._isTooltipVisible() ? this.hide() : this.show(undefined, origin);
447447
}
448448

@@ -452,10 +452,10 @@ export abstract class _MatTooltipBase<T extends _TooltipComponentBase>
452452
}
453453

454454
/** Create the overlay config and position strategy */
455-
private _createOverlay(origin?: { x: number; y: number; }): OverlayRef {
455+
private _createOverlay(origin?: {x: number; y: number}): OverlayRef {
456456
if (this._overlayRef) {
457-
const existingStrategy =
458-
this._overlayRef.getConfig().positionStrategy as FlexibleConnectedPositionStrategy;
457+
const existingStrategy = this._overlayRef.getConfig()
458+
.positionStrategy as FlexibleConnectedPositionStrategy;
459459

460460
if ((!this.positionAtOrigin || !origin) && existingStrategy._origin instanceof ElementRef) {
461461
return this._overlayRef;
@@ -471,7 +471,7 @@ export abstract class _MatTooltipBase<T extends _TooltipComponentBase>
471471
// Create connected position strategy that listens for scroll events to reposition.
472472
const strategy = this._overlay
473473
.position()
474-
.flexibleConnectedTo(this.positionAtOrigin ? (origin || this._elementRef) : this._elementRef)
474+
.flexibleConnectedTo(this.positionAtOrigin ? origin || this._elementRef : this._elementRef)
475475
.withTransformOriginOn(`.${this._cssClassPrefix}-tooltip`)
476476
.withFlexibleDimensions(false)
477477
.withViewportMargin(this._viewportMargin)
@@ -716,7 +716,11 @@ export abstract class _MatTooltipBase<T extends _TooltipComponentBase>
716716
'mouseenter',
717717
event => {
718718
this._setupPointerExitEventsIfNeeded();
719-
this.show(undefined, { x: (event as MouseEvent).x, y: (event as MouseEvent).y });
719+
let point = undefined;
720+
if ((event as MouseEvent).x !== undefined && (event as MouseEvent).y !== undefined) {
721+
point = event as MouseEvent;
722+
}
723+
this.show(undefined, point);
720724
},
721725
]);
722726
} else if (this.touchGestures !== 'off') {
@@ -725,8 +729,8 @@ export abstract class _MatTooltipBase<T extends _TooltipComponentBase>
725729
this._passiveListeners.push([
726730
'touchstart',
727731
event => {
728-
const touch = (event as TouchEvent).targetTouches[0];
729-
const origin = touch ? { x: touch.clientX, y: touch.clientY } : undefined;
732+
const touch = (event as TouchEvent).targetTouches?.[0];
733+
const origin = touch ? {x: touch.clientX, y: touch.clientY} : undefined;
730734
// Note that it's important that we don't `preventDefault` here,
731735
// because it can prevent click events from firing on the element.
732736
this._setupPointerExitEventsIfNeeded();

tools/public_api_guard/cdk/overlay.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -184,6 +184,7 @@ export class FlexibleConnectedPositionStrategy implements PositionStrategy {
184184
// (undocumented)
185185
detach(): void;
186186
dispose(): void;
187+
_origin: FlexibleConnectedPositionStrategyOrigin;
187188
positionChanges: Observable<ConnectedOverlayPositionChange>;
188189
get positions(): ConnectionPositionPair[];
189190
_preferredPositions: ConnectionPositionPair[];

tools/public_api_guard/material/tooltip.md

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -107,10 +107,19 @@ export abstract class _MatTooltipBase<T extends _TooltipComponentBase> implement
107107
_overlayRef: OverlayRef | null;
108108
get position(): TooltipPosition;
109109
set position(value: TooltipPosition);
110-
show(delay?: number): void;
110+
// (undocumented)
111+
get positionAtOrigin(): boolean;
112+
set positionAtOrigin(value: BooleanInput);
113+
show(delay?: number, origin?: {
114+
x: number;
115+
y: number;
116+
}): void;
111117
get showDelay(): number;
112118
set showDelay(value: NumberInput);
113-
toggle(): void;
119+
toggle(origin?: {
120+
x: number;
121+
y: number;
122+
}): void;
114123
get tooltipClass(): string | string[] | Set<string> | {
115124
[key: string]: any;
116125
};
@@ -125,7 +134,7 @@ export abstract class _MatTooltipBase<T extends _TooltipComponentBase> implement
125134
// (undocumented)
126135
protected _viewportMargin: number;
127136
// (undocumented)
128-
static ɵdir: i0.ɵɵDirectiveDeclaration<_MatTooltipBase<any>, never, never, { "position": "matTooltipPosition"; "disabled": "matTooltipDisabled"; "showDelay": "matTooltipShowDelay"; "hideDelay": "matTooltipHideDelay"; "touchGestures": "matTooltipTouchGestures"; "message": "matTooltip"; "tooltipClass": "matTooltipClass"; }, {}, never, never, false>;
137+
static ɵdir: i0.ɵɵDirectiveDeclaration<_MatTooltipBase<any>, never, never, { "position": "matTooltipPosition"; "positionAtOrigin": "matTooltipPositionAtOrigin"; "disabled": "matTooltipDisabled"; "showDelay": "matTooltipShowDelay"; "hideDelay": "matTooltipHideDelay"; "touchGestures": "matTooltipTouchGestures"; "message": "matTooltip"; "tooltipClass": "matTooltipClass"; }, {}, never, never, false>;
129138
// (undocumented)
130139
static ɵfac: i0.ɵɵFactoryDeclaration<_MatTooltipBase<any>, never>;
131140
}
@@ -135,6 +144,7 @@ export interface MatTooltipDefaultOptions {
135144
disableTooltipInteractivity?: boolean;
136145
hideDelay: number;
137146
position?: TooltipPosition;
147+
positionAtOrigin?: boolean;
138148
showDelay: number;
139149
touchendHideDelay: number;
140150
touchGestures?: TooltipTouchGestures;

0 commit comments

Comments
 (0)