Skip to content

Commit 3670e0f

Browse files
authored
fix(material/menu): render backdrop for context menu if explicitly opted in (#32845)
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.
1 parent 96de088 commit 3670e0f

File tree

3 files changed

+26
-2
lines changed

3 files changed

+26
-2
lines changed

src/material/menu/context-menu-trigger.spec.ts

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import {Component, signal} from '@angular/core';
1+
import {Component, signal, ViewChild} from '@angular/core';
22
import {ComponentFixture, fakeAsync, flush, TestBed} from '@angular/core/testing';
33
import {MatContextMenuTrigger} from './context-menu-trigger';
44
import {MatMenu} from './menu';
@@ -16,6 +16,10 @@ describe('context menu trigger', () => {
1616
return document.querySelector('.mat-mdc-menu-panel');
1717
}
1818

19+
function getBackdrop(): HTMLElement | null {
20+
return document.querySelector('.cdk-overlay-backdrop');
21+
}
22+
1923
beforeEach(() => {
2024
fixture = TestBed.createComponent(ContextMenuTest);
2125
fixture.detectChanges();
@@ -157,6 +161,21 @@ describe('context menu trigger', () => {
157161
fixture.detectChanges();
158162
expect(getMenu()).toBe(null);
159163
});
164+
165+
it('should not create a backdrop for context menu by default', () => {
166+
dispatchMouseEvent(getTrigger(), 'contextmenu', 10, 10);
167+
fixture.detectChanges();
168+
expect(getBackdrop()).toBeFalsy();
169+
expect(getMenu()).toBeTruthy();
170+
});
171+
172+
it('should create a backdrop for context menus if the menu explicitly opted into it', () => {
173+
fixture.componentInstance.menuInstance.hasBackdrop = true;
174+
dispatchMouseEvent(getTrigger(), 'contextmenu', 10, 10);
175+
fixture.detectChanges();
176+
expect(getBackdrop()).toBeTruthy();
177+
expect(getMenu()).toBeTruthy();
178+
});
160179
});
161180

162181
@Component({
@@ -185,6 +204,7 @@ describe('context menu trigger', () => {
185204
`,
186205
})
187206
class ContextMenuTest {
207+
@ViewChild(MatMenu) menuInstance!: MatMenu;
188208
showTrigger = signal(true);
189209
disabled = signal(false);
190210
opened = jasmine.createSpy('opened');

src/material/menu/menu-trigger-base.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -222,7 +222,7 @@ export abstract class MatMenuTriggerBase implements OnDestroy {
222222
overlayConfig.hasBackdrop =
223223
menu.hasBackdrop == null ? !this._triggersSubmenu() : menu.hasBackdrop;
224224
} else {
225-
overlayConfig.hasBackdrop = false;
225+
overlayConfig.hasBackdrop = menu.hasBackdrop ?? false;
226226
}
227227

228228
// We need the `hasAttached` check for the case where the user kicked off a removal animation,

src/material/menu/menu.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,10 @@ area and will be closed if the user clicks away.
5757
You can set up a `mat-menu` as a context menu by adding the `matContextMenuTriggerFor` directive
5858
to your container and binding it to a menu instance.
5959

60+
Note that by default context menus don't create a backdrop element in order to allow the user to
61+
right click somewhere else. You can opt into the backdrop by explicitly setting
62+
`[hasBackdrop]="true"` on the menu.
63+
6064
<!-- example(context-menu) -->
6165

6266
### Lazy rendering

0 commit comments

Comments
 (0)