diff --git a/projects/element-ng/tooltip/si-tooltip.directive.spec.ts b/projects/element-ng/tooltip/si-tooltip.directive.spec.ts index 064bdb967b..11940b1c57 100644 --- a/projects/element-ng/tooltip/si-tooltip.directive.spec.ts +++ b/projects/element-ng/tooltip/si-tooltip.directive.spec.ts @@ -73,6 +73,26 @@ describe('SiTooltipDirective', () => { expect(document.querySelector('.tooltip')).not.toBeInTheDocument(); }); + it('should hide tooltip on Escape key while trigger has focus', async () => { + button.dispatchEvent(new Event('focus')); + vi.advanceTimersByTime(0); + await fixture.whenStable(); + expect(document.querySelector('.tooltip')).toBeInTheDocument(); + + button.dispatchEvent(new KeyboardEvent('keydown', { key: 'Escape', bubbles: true })); + expect(document.querySelector('.tooltip')).not.toBeInTheDocument(); + }); + + it('should hide tooltip on Escape key while tooltip is open via hover', async () => { + button.dispatchEvent(new MouseEvent('mouseenter')); + vi.advanceTimersByTime(500); + await fixture.whenStable(); + expect(document.querySelector('.tooltip')).toBeInTheDocument(); + + document.dispatchEvent(new KeyboardEvent('keydown', { key: 'Escape' })); + expect(document.querySelector('.tooltip')).not.toBeInTheDocument(); + }); + it('should update tooltip content while open', async () => { button.dispatchEvent(new Event('focus')); vi.advanceTimersByTime(0); diff --git a/projects/element-ng/tooltip/si-tooltip.directive.ts b/projects/element-ng/tooltip/si-tooltip.directive.ts index 07ec29024e..7331a94bae 100644 --- a/projects/element-ng/tooltip/si-tooltip.directive.ts +++ b/projects/element-ng/tooltip/si-tooltip.directive.ts @@ -27,7 +27,8 @@ import { SiTooltipService, TooltipRef } from './si-tooltip.service'; '(mouseenter)': 'show()', '(touchstart)': 'hide()', '(focusout)': 'hide()', - '(mouseleave)': 'hide()' + '(mouseleave)': 'hide()', + '(document:keydown.escape)': 'isTooltipVisible && hide()' } }) export class SiTooltipDirective implements OnDestroy { @@ -60,6 +61,7 @@ export class SiTooltipDirective implements OnDestroy { readonly tooltipContext = input(); protected describedBy = `__tooltip_${SiTooltipDirective.idCounter++}`; + protected isTooltipVisible = false; private tooltipRef?: TooltipRef; private showTimeout?: ReturnType; @@ -98,6 +100,7 @@ export class SiTooltipDirective implements OnDestroy { tooltipContext: this.tooltipContext }); this.tooltipRef.show(); + this.isTooltipVisible = true; }, delay); } @@ -114,5 +117,6 @@ export class SiTooltipDirective implements OnDestroy { protected hide(): void { this.clearShowTimeout(); this.tooltipRef?.hide(); + this.isTooltipVisible = false; } }