From 2c0fa44ff373a6d63ef04dabe09fcba7bc86d0f7 Mon Sep 17 00:00:00 2001 From: Kristiyan Kostadinov Date: Tue, 24 Feb 2026 18:40:20 +0100 Subject: [PATCH] fix(material/menu): render backdrop for context menu if explicitly opted in When we introduced context menus, we disabled backdrops on them in order to mimic the native behavior where right clicking somewhere else moves the menu there. This seems to not be desirable for some users so these changes add some logic to enable the backdrop if the user explicitly requested it. Fixes #32350. --- .../menu/context-menu-trigger.spec.ts | 22 ++++++++++++++++++- src/material/menu/menu-trigger-base.ts | 2 +- src/material/menu/menu.md | 4 ++++ 3 files changed, 26 insertions(+), 2 deletions(-) diff --git a/src/material/menu/context-menu-trigger.spec.ts b/src/material/menu/context-menu-trigger.spec.ts index 8bf46c6651a1..a7c6243d3a36 100644 --- a/src/material/menu/context-menu-trigger.spec.ts +++ b/src/material/menu/context-menu-trigger.spec.ts @@ -1,4 +1,4 @@ -import {Component, signal} from '@angular/core'; +import {Component, signal, ViewChild} from '@angular/core'; import {ComponentFixture, fakeAsync, flush, TestBed} from '@angular/core/testing'; import {MatContextMenuTrigger} from './context-menu-trigger'; import {MatMenu} from './menu'; @@ -16,6 +16,10 @@ describe('context menu trigger', () => { return document.querySelector('.mat-mdc-menu-panel'); } + function getBackdrop(): HTMLElement | null { + return document.querySelector('.cdk-overlay-backdrop'); + } + beforeEach(() => { fixture = TestBed.createComponent(ContextMenuTest); fixture.detectChanges(); @@ -157,6 +161,21 @@ describe('context menu trigger', () => { fixture.detectChanges(); expect(getMenu()).toBe(null); }); + + it('should not create a backdrop for context menu by default', () => { + dispatchMouseEvent(getTrigger(), 'contextmenu', 10, 10); + fixture.detectChanges(); + expect(getBackdrop()).toBeFalsy(); + expect(getMenu()).toBeTruthy(); + }); + + it('should create a backdrop for context menus if the menu explicitly opted into it', () => { + fixture.componentInstance.menuInstance.hasBackdrop = true; + dispatchMouseEvent(getTrigger(), 'contextmenu', 10, 10); + fixture.detectChanges(); + expect(getBackdrop()).toBeTruthy(); + expect(getMenu()).toBeTruthy(); + }); }); @Component({ @@ -185,6 +204,7 @@ describe('context menu trigger', () => { `, }) class ContextMenuTest { + @ViewChild(MatMenu) menuInstance!: MatMenu; showTrigger = signal(true); disabled = signal(false); opened = jasmine.createSpy('opened'); diff --git a/src/material/menu/menu-trigger-base.ts b/src/material/menu/menu-trigger-base.ts index 1519ceeccd4d..beb574eee2cc 100644 --- a/src/material/menu/menu-trigger-base.ts +++ b/src/material/menu/menu-trigger-base.ts @@ -222,7 +222,7 @@ export abstract class MatMenuTriggerBase implements OnDestroy { overlayConfig.hasBackdrop = menu.hasBackdrop == null ? !this._triggersSubmenu() : menu.hasBackdrop; } else { - overlayConfig.hasBackdrop = false; + overlayConfig.hasBackdrop = menu.hasBackdrop ?? false; } // We need the `hasAttached` check for the case where the user kicked off a removal animation, diff --git a/src/material/menu/menu.md b/src/material/menu/menu.md index c0f5f11170af..b3ded2c9ecc7 100644 --- a/src/material/menu/menu.md +++ b/src/material/menu/menu.md @@ -57,6 +57,10 @@ area and will be closed if the user clicks away. You can set up a `mat-menu` as a context menu by adding the `matContextMenuTriggerFor` directive to your container and binding it to a menu instance. +Note that by default context menus don't create a backdrop element in order to allow the user to +right click somewhere else. You can opt into the backdrop by explicitly setting +`[hasBackdrop]="true"` on the menu. + ### Lazy rendering