mirror of
https://github.com/angular/angular.git
synced 2026-09-14 13:54:52 +08:00
fix(drawer): show backdrop in "side" mode if hasBackdrop is explicitly set to true (#10251)
Currently we only use `hasBackdrop` to hide the backdrop, however setting it to `true` explicitly also expresses an intent that the consumer might want the backdrop to always be shown. These changes make it so backdrop will also be shown for `side` drawers if `hasBackdrop` is set to `true`.
This commit is contained in:
committed by
Jeremy Elbourn
parent
0c64b15f3d
commit
583fe151fd
@@ -4,7 +4,7 @@
|
||||
|
||||
<div class="demo-sidenav-area" *ngIf="isLaunched">
|
||||
<mat-toolbar *ngIf="showHeader && !coverHeader">Header</mat-toolbar>
|
||||
<mat-sidenav-container>
|
||||
<mat-sidenav-container [hasBackdrop]="hasBackdrop">
|
||||
<mat-sidenav #start (open)="myinput.focus()" [mode]="mode"
|
||||
[fixedInViewport]="fixed" [fixedTopGap]="fixedTop" [fixedBottomGap]="fixedBottom">
|
||||
Start Side Sidenav
|
||||
@@ -41,6 +41,7 @@
|
||||
<h3>Sidenav</h3>
|
||||
<button mat-button (click)="start.toggle(undefined, 'mouse')">Toggle Start Side Sidenav</button>
|
||||
<button mat-button (click)="end.toggle(undefined, 'mouse')">Toggle End Side Sidenav</button>
|
||||
<mat-checkbox [(ngModel)]="hasBackdrop">Has backdrop</mat-checkbox>
|
||||
<mat-checkbox [(ngModel)]="fixed">Fixed mode</mat-checkbox>
|
||||
<mat-checkbox [(ngModel)]="coverHeader">Sidenav covers header/footer</mat-checkbox>
|
||||
</div>
|
||||
|
||||
@@ -25,6 +25,7 @@ export class SidenavDemo {
|
||||
showHeader = false;
|
||||
showFooter = false;
|
||||
modeIndex = 0;
|
||||
hasBackdrop: boolean;
|
||||
get mode() { return ['side', 'over', 'push'][this.modeIndex]; }
|
||||
get fixedTop() { return this.fixed && this.showHeader && !this.coverHeader ? 64 : 0; }
|
||||
get fixedBottom() { return this.fixed && this.showFooter && !this.coverHeader ? 64 : 0; }
|
||||
|
||||
@@ -45,6 +45,12 @@ $mat-drawer-over-drawer-z-index: 4;
|
||||
overflow: hidden;
|
||||
}
|
||||
}
|
||||
|
||||
// When the consumer explicitly enabled the backdrop,
|
||||
// we have to pull the side drawers above it.
|
||||
&.mat-drawer-container-explicit-backdrop .mat-drawer-side {
|
||||
z-index: $mat-drawer-backdrop-z-index;
|
||||
}
|
||||
}
|
||||
|
||||
.mat-drawer-backdrop {
|
||||
|
||||
@@ -643,6 +643,35 @@ describe('MatDrawerContainer', () => {
|
||||
expect(fixture.nativeElement.querySelector('.mat-drawer-backdrop')).toBeFalsy();
|
||||
}));
|
||||
|
||||
it('should be able to explicitly enable the backdrop in `side` mode', fakeAsync(() => {
|
||||
const fixture = TestBed.createComponent(BasicTestApp);
|
||||
const root = fixture.nativeElement;
|
||||
|
||||
fixture.componentInstance.drawer.mode = 'side';
|
||||
fixture.detectChanges();
|
||||
fixture.componentInstance.drawer.open();
|
||||
fixture.detectChanges();
|
||||
tick();
|
||||
fixture.detectChanges();
|
||||
|
||||
let backdrop = root.querySelector('.mat-drawer-backdrop.mat-drawer-shown');
|
||||
|
||||
expect(backdrop).toBeFalsy();
|
||||
|
||||
fixture.componentInstance.hasBackdrop = true;
|
||||
fixture.detectChanges();
|
||||
backdrop = root.querySelector('.mat-drawer-backdrop.mat-drawer-shown');
|
||||
|
||||
expect(backdrop).toBeTruthy();
|
||||
expect(fixture.componentInstance.drawer.opened).toBe(true);
|
||||
|
||||
backdrop.click();
|
||||
fixture.detectChanges();
|
||||
tick();
|
||||
|
||||
expect(fixture.componentInstance.drawer.opened).toBe(false);
|
||||
}));
|
||||
|
||||
});
|
||||
|
||||
|
||||
@@ -666,7 +695,7 @@ class DrawerContainerTwoDrawerTestApp {
|
||||
@Component({
|
||||
template: `
|
||||
<mat-drawer-container (backdropClick)="backdropClicked()" [hasBackdrop]="hasBackdrop">
|
||||
<mat-drawer #drawer position="start"
|
||||
<mat-drawer #drawer="matDrawer" position="start"
|
||||
(opened)="open()"
|
||||
(openedStart)="openStart()"
|
||||
(closed)="close()"
|
||||
@@ -683,8 +712,9 @@ class BasicTestApp {
|
||||
closeCount = 0;
|
||||
closeStartCount = 0;
|
||||
backdropClickedCount = 0;
|
||||
hasBackdrop = true;
|
||||
hasBackdrop: boolean | null = null;
|
||||
|
||||
@ViewChild('drawer') drawer: MatDrawer;
|
||||
@ViewChild('drawerButton') drawerButton: ElementRef;
|
||||
@ViewChild('openButton') openButton: ElementRef;
|
||||
@ViewChild('closeButton') closeButton: ElementRef;
|
||||
|
||||
+20
-11
@@ -430,6 +430,7 @@ export class MatDrawer implements AfterContentInit, AfterContentChecked, OnDestr
|
||||
styleUrls: ['drawer.css'],
|
||||
host: {
|
||||
'class': 'mat-drawer-container',
|
||||
'[class.mat-drawer-container-explicit-backdrop]': '_backdropOverride',
|
||||
},
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
encapsulation: ViewEncapsulation.None,
|
||||
@@ -458,19 +459,23 @@ export class MatDrawerContainer implements AfterContentInit, OnDestroy {
|
||||
set autosize(value: boolean) { this._autosize = coerceBooleanProperty(value); }
|
||||
private _autosize: boolean;
|
||||
|
||||
/** Whether the drawer container should have a backdrop while one of the sidenavs is open. */
|
||||
/**
|
||||
* Whether the drawer container should have a backdrop while one of the sidenavs is open.
|
||||
* If explicitly set to `true`, the backdrop will be enabled for drawers in the `side`
|
||||
* mode as well.
|
||||
*/
|
||||
@Input()
|
||||
get hasBackdrop() {
|
||||
if (this._hasBackdrop == null) {
|
||||
if (this._backdropOverride == null) {
|
||||
return !this._start || this._start.mode !== 'side' || !this._end || this._end.mode !== 'side';
|
||||
}
|
||||
|
||||
return this._hasBackdrop;
|
||||
return this._backdropOverride;
|
||||
}
|
||||
set hasBackdrop(value: any) {
|
||||
this._hasBackdrop = value == null ? null : coerceBooleanProperty(value);
|
||||
this._backdropOverride = value == null ? null : coerceBooleanProperty(value);
|
||||
}
|
||||
private _hasBackdrop: boolean | null;
|
||||
_backdropOverride: boolean | null;
|
||||
|
||||
/** Event emitted when the drawer backdrop is clicked. */
|
||||
@Output() readonly backdropClick: EventEmitter<void> = new EventEmitter<void>();
|
||||
@@ -663,8 +668,8 @@ export class MatDrawerContainer implements AfterContentInit, OnDestroy {
|
||||
|
||||
/** Whether the container is being pushed to the side by one of the drawers. */
|
||||
private _isPushed() {
|
||||
return (this._isDrawerOpen(this._start) && this._start!.mode != 'over') ||
|
||||
(this._isDrawerOpen(this._end) && this._end!.mode != 'over');
|
||||
return (this._isDrawerOpen(this._start) && this._start.mode != 'over') ||
|
||||
(this._isDrawerOpen(this._end) && this._end.mode != 'over');
|
||||
}
|
||||
|
||||
_onBackdropClicked() {
|
||||
@@ -675,16 +680,20 @@ export class MatDrawerContainer implements AfterContentInit, OnDestroy {
|
||||
_closeModalDrawer() {
|
||||
// Close all open drawers where closing is not disabled and the mode is not `side`.
|
||||
[this._start, this._end]
|
||||
.filter(drawer => drawer && !drawer.disableClose && drawer.mode !== 'side')
|
||||
.filter(drawer => drawer && !drawer.disableClose && this._canHaveBackdrop(drawer))
|
||||
.forEach(drawer => drawer!.close());
|
||||
}
|
||||
|
||||
_isShowingBackdrop(): boolean {
|
||||
return (this._isDrawerOpen(this._start) && this._start!.mode != 'side')
|
||||
|| (this._isDrawerOpen(this._end) && this._end!.mode != 'side');
|
||||
return (this._isDrawerOpen(this._start) && this._canHaveBackdrop(this._start)) ||
|
||||
(this._isDrawerOpen(this._end) && this._canHaveBackdrop(this._end));
|
||||
}
|
||||
|
||||
private _isDrawerOpen(drawer: MatDrawer | null): boolean {
|
||||
private _canHaveBackdrop(drawer: MatDrawer): boolean {
|
||||
return drawer.mode !== 'side' || !!this._backdropOverride;
|
||||
}
|
||||
|
||||
private _isDrawerOpen(drawer: MatDrawer | null): drawer is MatDrawer {
|
||||
return drawer != null && drawer.opened;
|
||||
}
|
||||
|
||||
|
||||
@@ -106,6 +106,7 @@ export class MatSidenav extends MatDrawer {
|
||||
styleUrls: ['drawer.css'],
|
||||
host: {
|
||||
'class': 'mat-drawer-container mat-sidenav-container',
|
||||
'[class.mat-drawer-container-explicit-backdrop]': '_backdropOverride',
|
||||
},
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
encapsulation: ViewEncapsulation.None,
|
||||
|
||||
Reference in New Issue
Block a user