Skip to content

Commit 3f91e72

Browse files
committed
fix(cdk/menu): close sibling triggers when opening a menu
Currently, when any sibling menu is opened then it overlaps and in cases it freezes and makes the screen unresponsive. This fix will close any sibling menu if its open Fixes #30881
1 parent 357cfd3 commit 3f91e72

File tree

2 files changed

+24
-2
lines changed

2 files changed

+24
-2
lines changed

src/cdk/menu/context-menu-trigger.ts

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ import {merge, partition} from 'rxjs';
2727
import {skip, takeUntil, skipWhile} from 'rxjs/operators';
2828
import {MENU_STACK, MenuStack} from './menu-stack';
2929
import {CdkMenuTriggerBase, MENU_TRIGGER} from './menu-trigger-base';
30+
import {CDK_MENU} from './menu-interface';
3031

3132
/** The preferred menu positions for the context menu. */
3233
const CONTEXT_MENU_POSITIONS = STANDARD_DROPDOWN_BELOW_POSITIONS.map(position => {
@@ -92,6 +93,9 @@ export class CdkContextMenuTrigger extends CdkMenuTriggerBase implements OnDestr
9293

9394
private readonly _changeDetectorRef = inject(ChangeDetectorRef);
9495

96+
/** The parent menu this trigger belongs to. */
97+
private readonly _parentMenu = inject(CDK_MENU, {optional: true});
98+
9599
/** Whether the context menu is disabled. */
96100
@Input({alias: 'cdkContextMenuDisabled', transform: booleanAttribute}) disabled: boolean = false;
97101

@@ -237,7 +241,7 @@ export class CdkContextMenuTrigger extends CdkMenuTriggerBase implements OnDestr
237241
this.overlayRef!.updatePosition();
238242
} else {
239243
this.opened.next();
240-
244+
this._closeSiblingTriggers();
241245
if (this.overlayRef) {
242246
(
243247
this.overlayRef.getConfig().positionStrategy as FlexibleConnectedPositionStrategy
@@ -251,4 +255,22 @@ export class CdkContextMenuTrigger extends CdkMenuTriggerBase implements OnDestr
251255
this._subscribeToOutsideClicks(userEvent);
252256
}
253257
}
258+
259+
/** Close out any sibling menu trigger menus. */
260+
private _closeSiblingTriggers() {
261+
if (this._parentMenu) {
262+
// If nothing was removed from the stack and the last element is not the parent item
263+
// that means that the parent menu is a menu bar since we don't put the menu bar on the
264+
// stack
265+
const isParentMenuBar =
266+
!this.menuStack.closeSubMenuOf(this._parentMenu) &&
267+
this.menuStack.peek() !== this._parentMenu;
268+
269+
if (isParentMenuBar) {
270+
this.menuStack.closeAll();
271+
}
272+
} else {
273+
this.menuStack.closeAll();
274+
}
275+
}
254276
}

src/cdk/menu/menu-trigger.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,7 @@ export class CdkMenuTrigger extends CdkMenuTriggerBase implements OnChanges, OnD
109109
open() {
110110
if (!this.isOpen() && this.menuTemplateRef != null) {
111111
this.opened.next();
112-
112+
this._closeSiblingTriggers();
113113
this.overlayRef = this.overlayRef || this._overlay.create(this._getOverlayConfig());
114114
this.overlayRef.attach(this.getMenuContentPortal());
115115
this._changeDetectorRef.markForCheck();

0 commit comments

Comments
 (0)