Skip to content

Commit

Permalink
fix(sidenav): prevent content from scrolling when sidenav is open
Browse files Browse the repository at this point in the history
  • Loading branch information
kara committed Apr 29, 2016
1 parent 9857f0f commit fea5923
Show file tree
Hide file tree
Showing 3 changed files with 42 additions and 14 deletions.
7 changes: 7 additions & 0 deletions src/components/sidenav/sidenav.scss
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,10 @@ $md-sidenav-push-background-color: md-color($md-background, dialog) !default;
// TODO(hansl): Update this with a more robust solution.
&[fullscreen] {
@include md-sidenav-fullscreen();

&.md-sidenav-opened {
overflow: hidden;
}
}

// Need this to take up space in the layout.
Expand Down Expand Up @@ -109,6 +113,9 @@ $md-sidenav-push-background-color: md-color($md-background, dialog) !default;
z-index: 3;
min-width: 5%;

// TODO(kara): revisit scrolling behavior for sidenavs
overflow-y: auto;

background-color: $md-sidenav-background-color;

@include md-sidenav-transition(0, -100%);
Expand Down
40 changes: 31 additions & 9 deletions src/components/sidenav/sidenav.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import {
Type,
ChangeDetectionStrategy,
EventEmitter,
Renderer
} from 'angular2/core';
import {BaseException} from 'angular2/src/facade/exceptions';
import {Dir} from '../../core/rtl/dir';
Expand Down Expand Up @@ -49,7 +50,7 @@ export class MdSidenav {
@Input() mode: 'over' | 'push' | 'side' = 'over';

/** Whether the sidenav is opened. */
@Input('opened') private _opened: boolean;
@Input('opened') private _opened: boolean = false;

/** Event emitted when the sidenav is being opened. Use this to synchronize animations. */
@Output('open-start') onOpenStart = new EventEmitter<void>();
Expand Down Expand Up @@ -247,7 +248,8 @@ export class MdSidenavLayout implements AfterContentInit {
get start() { return this._start; }
get end() { return this._end; }

constructor(@Optional() @Host() private _dir: Dir) {
constructor(@Optional() @Host() private _dir: Dir, private _element: ElementRef,
private _renderer: Renderer) {
// If a `Dir` directive exists up the tree, listen direction changes and update the left/right
// properties to point to the proper start/end.
if (_dir != null) {
Expand All @@ -258,9 +260,28 @@ export class MdSidenavLayout implements AfterContentInit {
ngAfterContentInit() {
// On changes, assert on consistency.
this._sidenavs.changes.subscribe(() => this._validateDrawers());
this._sidenavs.forEach((sidenav: MdSidenav) => this._watchSidenavToggle(sidenav));
this._validateDrawers();
}

/*
* Subscribes to sidenav events in order to set a class on the main layout element when the sidenav
* is open and the backdrop is visible. This ensures any overflow on the layout element is properly
* hidden.
* */
private _watchSidenavToggle(sidenav: MdSidenav): void {
if (!sidenav || sidenav.mode === 'side') { return; }
sidenav.onOpen.subscribe(() => this._setLayoutClass(sidenav, true));
sidenav.onClose.subscribe(() => this._setLayoutClass(sidenav, false));
}

/*
* Toggles the 'md-sidenav-opened' class on the main 'md-sidenav-layout' element.
* */
private _setLayoutClass(sidenav: MdSidenav, bool: boolean): void {
this._renderer.setElementClass(this._element.nativeElement, 'md-sidenav-opened', bool);
}


/** The sidenav at the start/end alignment, independent of direction. */
private _start: MdSidenav;
Expand Down Expand Up @@ -318,9 +339,13 @@ export class MdSidenavLayout implements AfterContentInit {
}
}

private _isShowingBackdrop() {
return (this._start != null && this._start.mode != 'side' && this._start.opened)
|| (this._end != null && this._end.mode != 'side' && this._end.opened);
private _isShowingBackdrop(): boolean {
return (this._isSidenavOpen(this._start) && this._start.mode != 'side')
|| (this._isSidenavOpen(this._end) && this._end.mode != 'side');
}

private _isSidenavOpen(side: MdSidenav): boolean {
return side != null && side.opened;
}

/**
Expand All @@ -330,10 +355,7 @@ export class MdSidenavLayout implements AfterContentInit {
* @private
*/
private _getSidenavEffectiveWidth(sidenav: MdSidenav, mode: string): number {
if (sidenav != null && sidenav.mode == mode && sidenav.opened) {
return sidenav._width;
}
return 0;
return (this._isSidenavOpen(sidenav) && sidenav.mode == mode) ? sidenav._width : 0;
}

private _getMarginLeft() {
Expand Down
9 changes: 4 additions & 5 deletions src/demo-app/demo-app.scss
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,13 @@
}

md-sidenav {
width: 15%;
min-width: 15%;

[md-button] {
width: 100%;
position: absolute;
position: relative;
bottom: 0;
margin-bottom: 24px;
margin: 24px 0;
}
}

Expand All @@ -39,5 +39,4 @@
h1 {
font-size: 20px;
}
}

}

0 comments on commit fea5923

Please sign in to comment.