From b0809ec11fe64ab724a374001a4acd4b3baa44f0 Mon Sep 17 00:00:00 2001 From: Andrey Dolgachev Date: Mon, 17 Nov 2025 20:22:22 -0800 Subject: [PATCH 1/2] fix(cdk/menu): enable inline popover inline menu trigger --- src/cdk/menu/context-menu-trigger.ts | 2 ++ src/cdk/menu/menu-bar.ts | 12 +++++++++++- src/cdk/menu/menu-trigger.ts | 2 ++ 3 files changed, 15 insertions(+), 1 deletion(-) diff --git a/src/cdk/menu/context-menu-trigger.ts b/src/cdk/menu/context-menu-trigger.ts index bf1b5a86ea67..7420a3710a6e 100644 --- a/src/cdk/menu/context-menu-trigger.ts +++ b/src/cdk/menu/context-menu-trigger.ts @@ -137,6 +137,7 @@ export class CdkContextMenuTrigger extends CdkMenuTriggerBase implements OnDestr positionStrategy: this._getOverlayPositionStrategy(coordinates), scrollStrategy: this.menuScrollStrategy(), direction: this._directionality || undefined, + usePopover: true, }); } @@ -150,6 +151,7 @@ export class CdkContextMenuTrigger extends CdkMenuTriggerBase implements OnDestr return createFlexibleConnectedPositionStrategy(this._injector, coordinates) .withLockedPosition() .withGrowAfterOpen() + .withPopoverLocation('inline') .withPositions(this.menuPosition ?? CONTEXT_MENU_POSITIONS); } diff --git a/src/cdk/menu/menu-bar.ts b/src/cdk/menu/menu-bar.ts index 5d09bc9c6e6d..90cb4c93179c 100644 --- a/src/cdk/menu/menu-bar.ts +++ b/src/cdk/menu/menu-bar.ts @@ -6,7 +6,7 @@ * found in the LICENSE file at https://angular.dev/license */ -import {AfterContentInit, Directive} from '@angular/core'; +import {inject, AfterContentInit, Directive, ElementRef} from '@angular/core'; import { DOWN_ARROW, ESCAPE, @@ -16,6 +16,7 @@ import { TAB, UP_ARROW, } from '../keycodes'; +import {_getEventTarget} from '../platform'; import {takeUntil} from 'rxjs/operators'; import {CdkMenuGroup} from './menu-group'; import {CDK_MENU} from './menu-interface'; @@ -43,6 +44,8 @@ import {CdkMenuBase} from './menu-base'; ], }) export class CdkMenuBar extends CdkMenuBase implements AfterContentInit { + private readonly _elementRef: ElementRef = inject(ElementRef); + /** The direction items in the menu flow. */ override readonly orientation = 'horizontal'; @@ -60,6 +63,13 @@ export class CdkMenuBar extends CdkMenuBase implements AfterContentInit { */ _handleKeyEvent(event: KeyboardEvent) { const keyManager = this.keyManager; + + const element = this._elementRef.nativeElement; + const target = _getEventTarget(event) as HTMLElement; + if (target !== element && target.parentElement !== element) { + return; + } + switch (event.keyCode) { case UP_ARROW: case DOWN_ARROW: diff --git a/src/cdk/menu/menu-trigger.ts b/src/cdk/menu/menu-trigger.ts index d37ab81a4205..6d77414b4bb9 100644 --- a/src/cdk/menu/menu-trigger.ts +++ b/src/cdk/menu/menu-trigger.ts @@ -276,6 +276,7 @@ export class CdkMenuTrigger extends CdkMenuTriggerBase implements OnChanges, OnD positionStrategy: this._getOverlayPositionStrategy(), scrollStrategy: this.menuScrollStrategy(), direction: this._directionality || undefined, + usePopover: true, }); } @@ -284,6 +285,7 @@ export class CdkMenuTrigger extends CdkMenuTriggerBase implements OnChanges, OnD return createFlexibleConnectedPositionStrategy(this._injector, this._elementRef) .withLockedPosition() .withFlexibleDimensions(false) + .withPopoverLocation('inline') .withPositions(this._getOverlayPositions()); } From d4e7a7096e0ceaf28717fe7b8afd576af8f15b6a Mon Sep 17 00:00:00 2001 From: Andrey Dolgachev Date: Tue, 25 Nov 2025 15:39:17 -0800 Subject: [PATCH 2/2] check events --- src/cdk/menu/menu-bar.ts | 1 + src/cdk/menu/menu.ts | 20 +++++++++++++++++++- 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/src/cdk/menu/menu-bar.ts b/src/cdk/menu/menu-bar.ts index 90cb4c93179c..1d18adf53776 100644 --- a/src/cdk/menu/menu-bar.ts +++ b/src/cdk/menu/menu-bar.ts @@ -64,6 +64,7 @@ export class CdkMenuBar extends CdkMenuBase implements AfterContentInit { _handleKeyEvent(event: KeyboardEvent) { const keyManager = this.keyManager; + // Now that menu overlays can be inlined, need to verify triggering on own events. const element = this._elementRef.nativeElement; const target = _getEventTarget(event) as HTMLElement; if (target !== element && target.parentElement !== element) { diff --git a/src/cdk/menu/menu.ts b/src/cdk/menu/menu.ts index 96182eff66cf..3766c4a738a1 100644 --- a/src/cdk/menu/menu.ts +++ b/src/cdk/menu/menu.ts @@ -6,8 +6,17 @@ * found in the LICENSE file at https://angular.dev/license */ -import {AfterContentInit, Directive, EventEmitter, inject, OnDestroy, Output} from '@angular/core'; +import { + AfterContentInit, + Directive, + ElementRef, + EventEmitter, + inject, + OnDestroy, + Output, +} from '@angular/core'; import {ESCAPE, hasModifierKey, LEFT_ARROW, RIGHT_ARROW, TAB} from '../keycodes'; +import {_getEventTarget} from '../platform'; import {takeUntil} from 'rxjs/operators'; import {CdkMenuGroup} from './menu-group'; import {CDK_MENU} from './menu-interface'; @@ -38,6 +47,7 @@ import {CdkMenuBase} from './menu-base'; ], }) export class CdkMenu extends CdkMenuBase implements AfterContentInit, OnDestroy { + private readonly _elementRef: ElementRef = inject(ElementRef); private _parentTrigger = inject(MENU_TRIGGER, {optional: true}); /** Event emitted when the menu is closed. */ @@ -71,6 +81,14 @@ export class CdkMenu extends CdkMenuBase implements AfterContentInit, OnDestroy */ _handleKeyEvent(event: KeyboardEvent) { const keyManager = this.keyManager; + + // Now that menu overlays can be inlined, need to verify triggering on own events. + const element = this._elementRef.nativeElement; + const target = _getEventTarget(event) as HTMLElement; + if (target !== element && target.parentElement !== element) { + return; + } + switch (event.keyCode) { case LEFT_ARROW: case RIGHT_ARROW: