Skip to content

Commit fae3eff

Browse files
authored
fix(angular/tooltip): not closing if escape is pressed while trigger isn't focused (#1034)
Currently, the tooltip's `keydown` handler is on the trigger, which means that it won't fire if the trigger doesn't have focus. This could happen when a tooltip was opened by hovering over the trigger. These changes use the `OverlayKeyboardDispatcher` to handle the events instead. angular/components#14434
1 parent 0421133 commit fae3eff

File tree

2 files changed

+30
-25
lines changed

2 files changed

+30
-25
lines changed

src/angular/tooltip/tooltip.spec.ts

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -540,9 +540,28 @@ describe('SbbTooltip', () => {
540540
expect(overlayContainerElement.textContent).toContain(initialTooltipMessage);
541541
}));
542542

543+
it('should hide when pressing escape', fakeAsync(() => {
544+
tooltipDirective.show();
545+
tick(0);
546+
fixture.detectChanges();
547+
tick(500);
548+
549+
expect(tooltipDirective._isTooltipVisible()).toBe(true);
550+
expect(overlayContainerElement.textContent).toContain(initialTooltipMessage);
551+
552+
dispatchKeyboardEvent(document.body, 'keydown', ESCAPE);
553+
tick(0);
554+
fixture.detectChanges();
555+
tick(500);
556+
fixture.detectChanges();
557+
558+
expect(tooltipDirective._isTooltipVisible()).toBe(false);
559+
expect(overlayContainerElement.textContent).toBe('');
560+
}));
561+
543562
it('should not throw when pressing ESCAPE', fakeAsync(() => {
544563
expect(() => {
545-
dispatchKeyboardEvent(buttonElement, 'keydown', ESCAPE);
564+
dispatchKeyboardEvent(document.body, 'keydown', ESCAPE);
546565
fixture.detectChanges();
547566
}).not.toThrow();
548567

@@ -555,7 +574,7 @@ describe('SbbTooltip', () => {
555574
tick(0);
556575
fixture.detectChanges();
557576

558-
const event = dispatchKeyboardEvent(buttonElement, 'keydown', ESCAPE);
577+
const event = dispatchKeyboardEvent(document.body, 'keydown', ESCAPE);
559578
fixture.detectChanges();
560579
flush();
561580

@@ -568,7 +587,7 @@ describe('SbbTooltip', () => {
568587
fixture.detectChanges();
569588

570589
const event = createKeyboardEvent('keydown', ESCAPE, undefined, { alt: true });
571-
dispatchEvent(buttonElement, event);
590+
dispatchEvent(document.body, event);
572591
fixture.detectChanges();
573592
flush();
574593

src/angular/tooltip/tooltip.ts

Lines changed: 8 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -306,10 +306,6 @@ export abstract class _SbbTooltipBase<T extends _TooltipComponentBase>
306306
if (_defaultOptions?.touchGestures) {
307307
this.touchGestures = _defaultOptions.touchGestures;
308308
}
309-
310-
_ngZone.runOutsideAngular(() => {
311-
_elementRef.nativeElement.addEventListener('keydown', this._handleKeydown);
312-
});
313309
}
314310

315311
ngAfterViewInit() {
@@ -347,7 +343,6 @@ export abstract class _SbbTooltipBase<T extends _TooltipComponentBase>
347343
}
348344

349345
// Clean up the event listeners set in the constructor
350-
nativeElement.removeEventListener('keydown', this._handleKeydown);
351346
this._passiveListeners.forEach(([event, listener]) => {
352347
nativeElement.removeEventListener(event, listener, passiveListenerOptions);
353348
});
@@ -423,18 +418,6 @@ export abstract class _SbbTooltipBase<T extends _TooltipComponentBase>
423418
return !!this._tooltipInstance && this._tooltipInstance.isVisible();
424419
}
425420

426-
/**
427-
* Handles the keydown events on the host element.
428-
* Needs to be an arrow function so that we can use it in addEventListener.
429-
*/
430-
private _handleKeydown = (event: KeyboardEvent) => {
431-
if (this._isTooltipVisible() && event.keyCode === ESCAPE && !hasModifierKey(event)) {
432-
event.preventDefault();
433-
event.stopPropagation();
434-
this._ngZone.run(() => this.hide(0));
435-
}
436-
};
437-
438421
/** Create the overlay config and position strategy */
439422
private _createOverlay(): OverlayRef {
440423
if (this._overlayRef) {
@@ -533,11 +516,14 @@ export abstract class _SbbTooltipBase<T extends _TooltipComponentBase>
533516

534517
this._overlayRef
535518
.keydownEvents()
536-
.pipe(
537-
filter((e) => e.keyCode === ESCAPE),
538-
takeUntil(this._destroyed)
539-
)
540-
.subscribe(() => this._tooltipInstance?._handleBodyInteraction());
519+
.pipe(takeUntil(this._destroyed))
520+
.subscribe((event) => {
521+
if (this._isTooltipVisible() && event.keyCode === ESCAPE && !hasModifierKey(event)) {
522+
event.preventDefault();
523+
event.stopPropagation();
524+
this._ngZone.run(() => this.hide(0));
525+
}
526+
});
541527

542528
this._overlayRef
543529
.outsidePointerEvents()

0 commit comments

Comments
 (0)