diff --git a/libs/components/src/menu/menu-trigger-for.directive.ts b/libs/components/src/menu/menu-trigger-for.directive.ts index bc174d14d23..528697600c4 100644 --- a/libs/components/src/menu/menu-trigger-for.directive.ts +++ b/libs/components/src/menu/menu-trigger-for.directive.ts @@ -1,5 +1,6 @@ // FIXME: Update this file to be type safe and remove this and next line // @ts-strict-ignore +import { hasModifierKey } from "@angular/cdk/keycodes"; import { Overlay, OverlayConfig, OverlayRef } from "@angular/cdk/overlay"; import { TemplatePortal } from "@angular/cdk/portal"; import { @@ -76,6 +77,13 @@ export class MenuTriggerForDirective implements OnDestroy { this.overlayRef.attach(templatePortal); this.closedEventsSub = this.getClosedEvents().subscribe((event: KeyboardEvent | undefined) => { + // Closing the menu is handled in this.destroyMenu, so we want to prevent the escape key + // from doing its normal default action, which would otherwise cause a parent component + // (like a dialog) or extension window to close + if (event?.key === "Escape" && !hasModifierKey(event)) { + event.preventDefault(); + } + if (["Tab", "Escape"].includes(event?.key)) { // Required to ensure tab order resumes correctly this.elementRef.nativeElement.focus(); diff --git a/libs/components/src/select/select.component.html b/libs/components/src/select/select.component.html index 84de9827b97..6d4c431f234 100644 --- a/libs/components/src/select/select.component.html +++ b/libs/components/src/select/select.component.html @@ -9,6 +9,7 @@ [clearable]="false" (close)="onClose()" appendTo="body" + [keyDownFn]="onKeyDown" >
diff --git a/libs/components/src/select/select.component.ts b/libs/components/src/select/select.component.ts index d2c48bf0f6e..909566bf1f8 100644 --- a/libs/components/src/select/select.component.ts +++ b/libs/components/src/select/select.component.ts @@ -1,6 +1,7 @@ // FIXME: Update this file to be type safe and remove this and next line // @ts-strict-ignore +import { hasModifierKey } from "@angular/cdk/keycodes"; import { Component, ContentChildren, @@ -185,4 +186,20 @@ export class SelectComponent implements BitFormFieldControl, ControlValueAcce protected onClose() { this.closed.emit(); } + + /** + * Prevent Escape key press from propagating to parent components + * (for example, parent dialog should not close when Escape is pressed in the select) + * + * @returns true to keep default key behavior; false to prevent default key behavior + * + * Needs to be arrow function to retain `this` scope. + */ + protected onKeyDown = (event: KeyboardEvent) => { + if (this.select.isOpen && event.key === "Escape" && !hasModifierKey(event)) { + event.stopPropagation(); + } + + return true; + }; }