docs(sidenav): update docs and add examples (#7775)

This commit is contained in:
mmalerba
2017-11-21 09:02:57 -08:00
committed by Jeremy Elbourn
parent 70aa3c2fa6
commit bd26e2ac22
30 changed files with 577 additions and 330 deletions
+1 -166
View File
@@ -1,166 +1 @@
**NOTE: The <code>mat-sidenav-layout</code> element is deprecated. <code>mat-sidenav-container</code>
should be used instead.**
# MatSidenav
MatSidenav is the side navigation component for Angular Material. It is composed of two components: `<mat-sidenav-container>` and `<mat-sidenav>`.
## Screenshots
<img src="https://material.angularjs.org/material2_assets/sidenav-example.png">
## `<mat-sidenav-container>`
The parent component. Contains the code necessary to coordinate one or two sidenav and the backdrop.
## `<mat-sidenav>`
The sidenav panel.
### Bound Properties
| Name | Type | Description |
| --- | --- | --- |
| `position` | `"start"\|"end"` | The position of this sidenav. In LTR direction, `"start"` will be shown on the left, `"end"` on the right. In RTL, it is reversed. `"start"` is used by default. If there is more than 1 sidenav on either side the container will be considered invalid and none of the sidenavs will be visible or toggleable until the container is valid again. |
| `mode` | `"over"\|"push"\|"side"` | The mode or styling of the sidenav, default being `"over"`. With `"over"` the sidenav will appear above the content, and a backdrop will be shown. With `"push"` the sidenav will push the content of the `<mat-sidenav-container>` to the side, and show a backdrop over it. `"side"` will resize the content and keep the sidenav opened. Clicking the backdrop will close sidenavs that do not have `mode="side"`. |
| `opened` | `boolean` | Whether or not the sidenav is opened. Use this binding to open/close the sidenav. |
### Events
| Name | Description |
| --- | --- |
| `open-start` | Emitted when the sidenav is starting opening. This should only be used to coordinate animations. |
| `close-start` | Emitted when the sidenav is starting closing. This should only be used to coordinate animations. |
| `open` | Emitted when the sidenav is done opening. Use this for, e.g., setting focus on controls or updating state. |
| `close` | Emitted when the sidenav is done closing. |
### Methods
| Signature | Description |
| --- | --- |
| `open(): Promise<void>` | Open the sidenav. Equivalent to `opened = true`. Returns a promise that will resolve when the animation completes, or be rejected if the animation was cancelled. |
| `close(): Promise<void>` | Close the sidenav. Equivalent to `opened = false`. Returns a promise that will resolve when the animation completes, or be rejected if the animation was cancelled. |
| `toggle(): Promise<void>` | Toggle the sidenav. This is equivalent to `opened = !opened`. Returns a promise that will resolve when the animation completes, or be rejected if the animation was cancelled. |
### Notes
The `<mat-sidenav>` will resize based on its content. You can also set its width in CSS, like so:
```css
mat-sidenav {
width: 200px;
}
```
Try to avoid percent based width as `resize` events are not (yet) supported.
## Examples
Here's a simple example of using the sidenav:
```html
<app>
<mat-sidenav-container>
<mat-sidenav #start (open)="closeStartButton.focus()">
Start Sidenav.
<br>
<button mat-button #closeStartButton (click)="start.close()">Close</button>
</mat-sidenav>
<mat-sidenav #end position="end">
End Sidenav.
<button mat-button (click)="end.close()">Close</button>
</mat-sidenav>
My regular content. This will be moved into the proper DOM at runtime.
<button mat-button (click)="start.open()">Open start sidenav</button>
<button mat-button (click)="end.open()">Open end sidenav</button>
</mat-sidenav-container>
</app>
```
For a fullscreen sidenav, the recommended approach is set up the DOM such that the
`mat-sidenav-container` can naturally take up the full space:
```html
<app>
<mat-sidenav-container>
<mat-sidenav mode="side" opened="true">Drawer content</mat-sidenav>
<div class="my-content">Main content</div>
</mat-sidenav-container>
</app>
```
```css
html, body, material-app, mat-sidenav-container, .my-content {
margin: 0;
width: 100%;
height: 100%;
}
```
For a sidenav with a FAB (or other floating element), the recommended approach is to place the FAB
outside of the scrollable region and absolutely position it.
```html
<app>
<mat-sidenav-container class="my-container">
<mat-sidenav mode="side" opened="true">
<button mat-mini-fab class="my-fab">
<mat-icon>add</mat-icon>
</button>
<div class="my-scrolling-content">
Lorem ipsum dolor sit amet, pede a libero aenean phasellus, lectus metus sint ut risus,
fusce vel in pellentesque. Nisl rutrum etiam morbi consectetuer tempor magna, aenean nullam
nunc id, neque vivamus interdum sociis nulla scelerisque sem, dolor id wisi turpis magna
aliquam magna. Risus accumsan hac eget etiam donec sed, senectus erat mattis quam, tempor
vel urna occaecat cras, metus urna augue nec at. Et morbi amet dui praesent, nec eu at,
ligula ipsum dui sollicitudin, quis nisl massa viverra ligula, mauris fermentum orci arcu
enim fringilla. Arcu erat nulla in aenean lacinia ullamcorper, urna ante nam et sagittis,
tristique vehicula nibh ipsum vivamus, proin proin. Porta commodo nibh quis libero amet.
Taciti dui, sapien consectetuer.
</div>
</mat-sidenav>
<button mat-mini-fab class="my-fab">
<mat-icon>add</mat-icon>
</button>
<div class="my-scrolling-content">
Lorem ipsum dolor sit amet, pede a libero aenean phasellus, lectus metus sint ut risus, fusce
vel in pellentesque. Nisl rutrum etiam morbi consectetuer tempor magna, aenean nullam nunc id,
neque vivamus interdum sociis nulla scelerisque sem, dolor id wisi turpis magna aliquam magna.
Risus accumsan hac eget etiam donec sed, senectus erat mattis quam, tempor vel urna occaecat
cras, metus urna augue nec at. Et morbi amet dui praesent, nec eu at, ligula ipsum dui
sollicitudin, quis nisl massa viverra ligula, mauris fermentum orci arcu enim fringilla. Arcu
erat nulla in aenean lacinia ullamcorper, urna ante nam et sagittis, tristique vehicula nibh
ipsum vivamus, proin proin. Porta commodo nibh quis libero amet. Taciti dui, sapien
consectetuer.
</div>
</mat-sidenav-container>
</app>
```
```css
.my-container {
width: 500px;
height: 300px;
}
.my-container .mat-sidenav {
max-width: 200px;
}
.my-container .mat-sidenav-content,
.my-container mat-sidenav {
display: flex;
}
.my-scrolling-content {
overflow: auto;
}
button.my-fab {
position: absolute;
right: 20px;
bottom: 10px;
}
```
Please see the official documentation at https://material.angular.io/components/component/sidenav
+159 -58
View File
@@ -1,44 +1,140 @@
`<mat-sidenav>` is a panel that can be placed next to or above some primary content. A sidenav is
typically used for navigation, but can contain any content.
Angular Material provides two sets of components designed to add collapsible side content (often
navigation, though it can be any content) alongside some primary content. These are the sidenav and
drawer components.
The sidenav components are designed to add side content to a fullscreen app. To set up a sidenav we
use three components: `<mat-sidenav-container>` which acts as a structural container for our content
and sidenav, `<mat-sidenav-content>` which represents the main content, and `<mat-sidenav>` which
represents the added side content.
<!-- example(sidenav-overview) -->
The sidenav and its associated content live inside of an `<mat-sidenav-container>`:
```html
<mat-sidenav-container>
<mat-sidenav>
<!-- sidenav content -->
</mat-sidenav>
The drawer component is designed to add side content to a small section of your app. This is
accomplished using the `<mat-drawer-container>`, `<mat-drawer-content>`, and `<mat-drawer>`
components, which are analogous to their sidenav equivalents. Rather than adding side content to the
app as a whole, these are designed to add side content to a small section of your app. They support
almost all of the same features, but do not support fixed positioning.
<!-- primary content -->
<!-- example(sidenav-drawer-overview) -->
### Specifying the main and side content
Both the main and side content should be placed inside of the `<mat-sidenav-container>`, content
that you don't want to be affected by the sidenav, such as a header or footer, can be placed outside
of the container.
The side content should be wrapped in a `<mat-sidenav>` element. The `position` property can be used
to specify which end of the main content to place the side content on. `position` can be either
`start` or `end` which places the side content on the left or right respectively in left-to-right
languages. If the `position` is not set, the default value of `start` will be assumed. A
`<mat-sidenav-container>` can have up to two `<mat-sidenav>` elements total, but only one for any
given side.
The main content should be wrapped in a `<mat-sidenav-content>`. If no `<mat-sidenav-content>` is
specified for a `<mat-sidenav-container>`, one will be created implicitly and all of the content
inside the `<mat-sidenav-container>` other than the `<mat-sidenav>` elements will be placed inside
of it.
<!-- example(sidenav-position) -->
The following are examples of valid sidenav layouts:
```html
<!-- Creates a layout with a left-positioned sidenav and explicit content. -->
<mat-sidenav-container>
<mat-sidenav>Start</mat-sidenav>
<mat-sidenav-content>Main</mat-sidenav-content>
</mat-sidenav-container>
```
A sidenav container may contain one or two `<mat-sidenav>` elements. When there are two
`<mat-sidenav>` elements, each must be placed on a different side of the container.
See the section on positioning below.
```html
<!-- Creates a layout with a left and right sidenav and implicit content. -->
<mat-sidenav-container>
<mat-sidenav>Start</mat-sidenav>
<mat-sidenav position="end">End</mat-sidenav>
<section>Main</section>
</mat-sidenav-container>
```
### Sidenav mode
The sidenav can render in one of three different ways based on the `mode` property.
```html
<!-- Creates an empty sidenav container with no sidenavs and implicit empty content. -->
<mat-sidenav-container></mat-sidenav-container>
```
| Mode | Description |
|------|-------------------------------------------------------------------------------------------|
| over | Sidenav floats _over_ the primary content, which is covered by a backdrop |
| push | Sidenav _pushes_ the primary content out of its way, also covering it with a backdrop |
| side | Sidenav appears _side-by-side_ with the primary content |
And these are examples of invalid sidenav layouts:
Using the `side` mode on mobile devices can affect the performance and is also not recommended by the
[Material Design specification](https://material.io/guidelines/patterns/navigation-drawer.html#navigation-drawer-behavior).
```html
<!-- Invalid because there are two `start` position sidenavs. -->
<mat-sidenav-container>
<mat-sidenav>Start</mat-sidenav>
<mat-sidenav position="start">Start 2</mat-sidenav>
</mat-sidenav-container>
```
### Positioning the sidenav
The `position` property determines whether the sidenav appears at the `"start"` or `"end"` of the
container. This is affected by the current text direction ("ltr" or "rtl"). By default, the sidenav
appears at the start of the container.
```html
<!-- Invalid because there are multiple `<mat-sidenav-content>` elements. -->
<mat-sidenav-container>
<mat-sidenav-content>Main</mat-sidenav-content>
<mat-sidenav-content>Main 2</mat-sidenav-content>
</mat-sidenav-container>
```
```html
<!-- Invalid because the `<mat-sidenav>` is outside of the `<mat-sidenav-container>`. -->
<mat-sidenav-container></mat-sidenav-container>
<mat-sidenav></mat-sidenav>
```
### Sizing the sidenav
The `<mat-sidenav>` will, by default, fit the size of its content. The width can be explicitly set
via CSS:
These same rules all apply to the drawer components as well.
### Opening and closing a sidenav
A `<mat-sidenav>` can be opened or closed using the `open()`, `close()` and `toggle()` methods. Each
of these methods returns a `Promise<boolean>` that will be resolved with `true` when the sidenav
finishes opening or `false` when it finishes closing.
The opened state can also be set via a property binding in the template using the `opened` property.
The property supports 2-way binding.
`<mat-sidenav>` also supports output properties for just open and just close events, The `(opened)`
and `(closed)` properties respectively.
<!-- example(sidenav-open-close) -->
All of these properties and methods work on `<mat-drawer>` as well.
### Changing the sidenav's behavior
The `<mat-sidenav>` can render in one of three different ways based on the `mode` property.
| Mode | Description |
|--------|-----------------------------------------------------------------------------------------|
| `over` | Sidenav floats over the primary content, which is covered by a backdrop |
| `push` | Sidenav pushes the primary content out of its way, also covering it with a backdrop |
| `side` | Sidenav appears side-by-side with the main content, shrinking the main content's width to make space for the sidenav. |
If no `mode` is specified, `over` is used by default.
<!-- example(sidenav-mode) -->
`<mat-drawer>` also supports all of these same modes.
### Disabling automatic close
Clicking on the backdrop or pressing the <kbd>Esc</kbd> key will normally close an open sidenav.
However, this automatic closing behavior can be disabled by setting the `disableClose` property on
the `<mat-sidenav>` or `<mat-drawer>` that you want to disable the behavior for.
Custom handling for <kbd>Esc</kbd> can be done by adding a keydown listener to the `<mat-sidenav>`.
Custom handling for backdrop clicks can be done via the `(backdropClick)` output property on
`<mat-sidenav-container>`.
<!-- example(sidenav-disable-close) -->
### Setting the sidenav's size
The `<mat-sidenav>` and `<mat-drawer>` will, by default, fit the size of its content. The width can
be explicitly set via CSS:
```css
mat-sidenav {
@@ -48,37 +144,42 @@ mat-sidenav {
Try to avoid percent based width as `resize` events are not (yet) supported.
For a fullscreen sidenav, the recommended approach is set up the DOM such that the
`<mat-sidenav-container>` can naturally take up the full space:
### Fixed position sidenavs
```html
<app>
<mat-sidenav-container>
<mat-sidenav mode="side" opened="true">Drawer content</mat-sidenav>
<div class="my-content">Main content</div>
</mat-sidenav-container>
</app>
```
```css
html, body, material-app, mat-sidenav-container, .my-content {
margin: 0;
width: 100%;
height: 100%;
}
```
For `<mat-sidenav>` only (not `<mat-drawer>`) fixed positioning is supported. It can be enabled by
setting the `fixedInViewport` property. Additionally, top and bottom space can be set via the
`fixedTopGap` and `fixedBottomGap`. These properties accept a pixel value amount of space to add at
the top or bottom.
### FABs inside sidenav
For a sidenav with a FAB (Floating Action Button) or other floating element, the recommended approach is to place the FAB
outside of the scrollable region and absolutely position it.
<!-- example(sidenav-fixed) -->
### Creating a responsive layout for mobile & desktop
### Disabling closing of sidenav
By default, sidenav can be closed either by clicking on the backdrop or by pressing <kbd>ESCAPE</kbd>.
The `disableClose` attribute can be set on `mat-sidenav` to disable automatic closing when the backdrop
is clicked or <kbd>ESCAPE</kbd> is pressed. To add custom logic on backdrop click, add a `(backdropClick)` listener to
`mat-sidenav-container`. For custom <kbd>ESCAPE</kbd> logic, a standard `(keydown)` listener will suffice.
```html
<mat-sidenav-container (backdropClick)="customBackdropClickHandler()">
<mat-sidenav disableClose (keydown)="customKeydownHandler($event)"></mat-sidenav>
</mat-sidenav-container>
```
A sidenav often needs to behave differently on a mobile vs a desktop display. On a desktop, it may
make sense to have just the content section scroll. However, on mobile you often want the body to be
the element that scrolls; this allows the address bar to auto-hide. The sidenav can be styled with
CSS to adjust to either type of device.
<!-- example(sidenav-responsive) -->
### Accessibility
The `<mat-sidenav>` an `<mat-sidenav-content>` should each be given an appropriate `role` attribute
depending on the context in which they are used.
For example, a `<mat-sidenav>` that contains links
to other pages might be marked `role="navigation"`, whereas one that contains a table of
contents about might be marked as `role="directory"`. If there is no more specific role that
describes your sidenav, `role="region"` is recommended.
Similarly, the `<mat-sidenav-content>` should be given a role based on what it contains. If it
represents the primary content of the page, it may make sense to mark it `role="main"`. If no more
specific role makes sense, `role="region"` is again a good fallback.
### Troubleshooting
#### Error: A drawer was already declared for 'position="..."'
This error is thrown if you have more than one sidenav or drawer in a given container with the same
`position`. The `position` property defaults to `start`, so the issue may just be that you forgot to
mark the `end` sidenav with `position="end"`.
+54 -6
View File
@@ -96,8 +96,14 @@ import {SelectOverviewExample} from './select-overview/select-overview-example';
import {SelectPanelClassExample} from './select-panel-class/select-panel-class-example';
import {SelectResetExample} from './select-reset/select-reset-example';
import {SelectValueBindingExample} from './select-value-binding/select-value-binding-example';
import {SidenavFabExample} from './sidenav-fab/sidenav-fab-example';
import {SidenavDisableCloseExample} from './sidenav-disable-close/sidenav-disable-close-example';
import {SidenavDrawerOverviewExample} from './sidenav-drawer-overview/sidenav-drawer-overview-example';
import {SidenavFixedExample} from './sidenav-fixed/sidenav-fixed-example';
import {SidenavModeExample} from './sidenav-mode/sidenav-mode-example';
import {SidenavOpenCloseExample} from './sidenav-open-close/sidenav-open-close-example';
import {SidenavOverviewExample} from './sidenav-overview/sidenav-overview-example';
import {SidenavPositionExample} from './sidenav-position/sidenav-position-example';
import {SidenavResponsiveExample} from './sidenav-responsive/sidenav-responsive-example';
import {SlideToggleConfigurableExample} from './slide-toggle-configurable/slide-toggle-configurable-example';
import {SlideToggleFormsExample} from './slide-toggle-forms/slide-toggle-forms-example';
import {SlideToggleOverviewExample} from './slide-toggle-overview/slide-toggle-overview-example';
@@ -620,18 +626,54 @@ export const EXAMPLE_COMPONENTS = {
additionalFiles: null,
selectorName: null
},
'sidenav-fab': {
title: 'Sidenav with a FAB',
component: SidenavFabExample,
'sidenav-disable-close': {
title: 'Sidenav with custom escape and backdrop click behavior ',
component: SidenavDisableCloseExample,
additionalFiles: null,
selectorName: null
},
'sidenav-drawer-overview': {
title: 'Basic drawer ',
component: SidenavDrawerOverviewExample,
additionalFiles: null,
selectorName: null
},
'sidenav-fixed': {
title: 'Fixed sidenav ',
component: SidenavFixedExample,
additionalFiles: null,
selectorName: null
},
'sidenav-mode': {
title: 'Sidenav with configurable mode ',
component: SidenavModeExample,
additionalFiles: null,
selectorName: null
},
'sidenav-open-close': {
title: 'Sidenav open & close behavior ',
component: SidenavOpenCloseExample,
additionalFiles: null,
selectorName: null
},
'sidenav-overview': {
title: 'Basic sidenav',
title: 'Basic sidenav ',
component: SidenavOverviewExample,
additionalFiles: null,
selectorName: null
},
'sidenav-position': {
title: 'Implicit main content with two sidenavs ',
component: SidenavPositionExample,
additionalFiles: null,
selectorName: null
},
'sidenav-responsive': {
title: 'Responsive sidenav ',
component: SidenavResponsiveExample,
additionalFiles: null,
selectorName: null
},
'slide-toggle-configurable': {
title: 'Configurable slide-toggle',
component: SlideToggleConfigurableExample,
@@ -850,8 +892,14 @@ export const EXAMPLE_LIST = [
SelectPanelClassExample,
SelectResetExample,
SelectValueBindingExample,
SidenavFabExample,
SidenavDisableCloseExample,
SidenavDrawerOverviewExample,
SidenavFixedExample,
SidenavModeExample,
SidenavOpenCloseExample,
SidenavOverviewExample,
SidenavPositionExample,
SidenavResponsiveExample,
SlideToggleConfigurableExample,
SlideToggleFormsExample,
SlideToggleOverviewExample,
@@ -0,0 +1,7 @@
.example-container {
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
}
@@ -0,0 +1,13 @@
<mat-sidenav-container
class="example-container" (backdropClick)="close('backdrop')" *ngIf="shouldRun">
<mat-sidenav #sidenav (keydown.escape)="close('escape')" disableClose>
<p><button mat-button (click)="close('toggle button')">Toggle</button></p>
</mat-sidenav>
<mat-sidenav-content>
<p><button mat-button (click)="sidenav.open()">Open</button></p>
<p>Closed due to: {{reason}}</p>
</mat-sidenav-content>
</mat-sidenav-container>
<div *ngIf="!shouldRun">Please open in Plunker to see result</div>
@@ -0,0 +1,21 @@
import {Component, ViewChild} from '@angular/core';
import {MatSidenav} from '@angular/material/sidenav';
/** @title Sidenav with custom escape and backdrop click behavior */
@Component({
selector: 'sidenav-disable-close-example',
templateUrl: 'sidenav-disable-close-example.html',
styleUrls: ['sidenav-disable-close-example.css'],
})
export class SidenavDisableCloseExample {
@ViewChild('sidenav') sidenav: MatSidenav;
reason = '';
close(reason: string) {
this.reason = reason;
this.sidenav.close();
}
shouldRun = [/(^|\.)plnkr\.co$/, /(^|\.)stackblitz\.io$/].some(h => h.test(window.location.host));
}
@@ -0,0 +1,6 @@
.example-container {
width: 400px;
height: 200px;
margin: 10px;
border: 1px solid #555;
}
@@ -0,0 +1,4 @@
<mat-drawer-container class="example-container">
<mat-drawer mode="side" opened="true">Drawer content</mat-drawer>
<mat-drawer-content>Main content</mat-drawer-content>
</mat-drawer-container>
@@ -0,0 +1,9 @@
import {Component} from '@angular/core';
/** @title Basic drawer */
@Component({
selector: 'sidenav-drawer-overview-example',
templateUrl: 'sidenav-drawer-overview-example.html',
styleUrls: ['sidenav-drawer-overview-example.css'],
})
export class SidenavDrawerOverviewExample {}
@@ -1,26 +0,0 @@
.example-sidenav-fab-container {
width: 500px;
height: 300px;
border: 1px solid rgba(0, 0, 0, 0.5);
}
.example-sidenav-fab-container mat-sidenav {
max-width: 200px;
}
.example-sidenav-fab-container .mat-sidenav-content,
.example-sidenav-fab-container mat-sidenav {
display: flex;
overflow: visible;
}
.example-scrolling-content {
overflow: auto;
height: 100%;
}
.example-fab.mat-mini-fab {
position: absolute;
right: 20px;
bottom: 10px;
}
@@ -1,32 +0,0 @@
<mat-sidenav-container class="example-sidenav-fab-container">
<mat-sidenav #sidenav mode="side" opened="true">
<button mat-mini-fab class="example-fab" (click)="sidenav.toggle()">
<mat-icon>add</mat-icon>
</button>
<div class="example-scrolling-content">
Lorem ipsum dolor sit amet, pede a libero aenean phasellus, lectus metus sint ut risus,
fusce vel in pellentesque. Nisl rutrum etiam morbi consectetuer tempor magna, aenean nullam
nunc id, neque vivamus interdum sociis nulla scelerisque sem, dolor id wisi turpis magna
aliquam magna. Risus accumsan hac eget etiam donec sed, senectus erat mattis quam, tempor
vel urna occaecat cras, metus urna augue nec at. Et morbi amet dui praesent, nec eu at,
ligula ipsum dui sollicitudin, quis nisl massa viverra ligula, mauris fermentum orci arcu
enim fringilla. Arcu erat nulla in aenean lacinia ullamcorper, urna ante nam et sagittis,
tristique vehicula nibh ipsum vivamus, proin proin. Porta commodo nibh quis libero amet.
Taciti dui, sapien consectetuer.
</div>
</mat-sidenav>
<button mat-mini-fab class="example-fab" (click)="sidenav.toggle()">
<mat-icon>add</mat-icon>
</button>
<div class="example-scrolling-content">
Lorem ipsum dolor sit amet, pede a libero aenean phasellus, lectus metus sint ut risus, fusce
vel in pellentesque. Nisl rutrum etiam morbi consectetuer tempor magna, aenean nullam nunc id,
neque vivamus interdum sociis nulla scelerisque sem, dolor id wisi turpis magna aliquam magna.
Risus accumsan hac eget etiam donec sed, senectus erat mattis quam, tempor vel urna occaecat
cras, metus urna augue nec at. Et morbi amet dui praesent, nec eu at, ligula ipsum dui
sollicitudin, quis nisl massa viverra ligula, mauris fermentum orci arcu enim fringilla. Arcu
erat nulla in aenean lacinia ullamcorper, urna ante nam et sagittis, tristique vehicula nibh
ipsum vivamus, proin proin. Porta commodo nibh quis libero amet. Taciti dui, sapien
consectetuer.
</div>
</mat-sidenav-container>
@@ -1,13 +0,0 @@
import {Component, ViewEncapsulation} from '@angular/core';
/**
* @title Sidenav with a FAB
*/
@Component({
selector: 'sidenav-fab-example',
templateUrl: 'sidenav-fab-example.html',
styleUrls: ['sidenav-fab-example.css'],
encapsulation: ViewEncapsulation.None,
preserveWhitespaces: false,
})
export class SidenavFabExample {}
@@ -0,0 +1,29 @@
.example-container {
position: absolute;
top: 60px;
bottom: 60px;
left: 0;
right: 0;
}
.example-sidenav {
display: flex;
align-items: center;
justify-content: center;
width: 200px;
background: rgba(255, 0, 0, 0.5);
}
.example-header {
position: fixed;
top: 0;
left: 0;
right: 0;
}
.example-footer {
position: fixed;
bottom: 0;
left: 0;
right: 0;
}
@@ -0,0 +1,26 @@
<ng-container *ngIf="shouldRun">
<mat-toolbar class="example-header">Header</mat-toolbar>
<mat-sidenav-container class="example-container">
<mat-sidenav #sidenav mode="side" opened="true" class="example-sidenav"
[fixedInViewport]="options.value.fixed" [fixedTopGap]="options.value.top"
[fixedBottomGap]="options.value.bottom">
{{options.value.fixed ? 'Fixed' : 'Non-fixed'}} Sidenav
</mat-sidenav>
<mat-sidenav-content [formGroup]="options">
<p><mat-checkbox formControlName="fixed">Fixed</mat-checkbox></p>
<p><mat-form-field>
<input matInput type="number" formControlName="top" placeholder="Top gap">
</mat-form-field></p>
<p><mat-form-field>
<input matInput type="number" formControlName="bottom" placeholder="Bottom gap">
</mat-form-field></p>
<p><button mat-button (click)="sidenav.toggle()">Toggle</button></p>
</mat-sidenav-content>
</mat-sidenav-container>
<mat-toolbar class="example-footer">Footer</mat-toolbar>
</ng-container>
<div *ngIf="!shouldRun">Please open in Plunker to see result</div>
@@ -0,0 +1,22 @@
import {Component} from '@angular/core';
import {FormBuilder, FormGroup} from '@angular/forms';
/** @title Fixed sidenav */
@Component({
selector: 'sidenav-fixed-example',
templateUrl: 'sidenav-fixed-example.html',
styleUrls: ['sidenav-fixed-example.css'],
})
export class SidenavFixedExample {
options: FormGroup;
constructor(fb: FormBuilder) {
this.options = fb.group({
'fixed': false,
'top': 0,
'bottom': 0,
});
}
shouldRun = [/(^|\.)plnkr\.co$/, /(^|\.)stackblitz\.io$/].some(h => h.test(window.location.host));
}
@@ -0,0 +1,14 @@
.example-container {
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
}
.example-radio-group {
display: block;
border: 1px solid #555;
margin: 20px;
padding: 10px;
}
@@ -0,0 +1,27 @@
<mat-sidenav-container class="example-container" *ngIf="shouldRun">
<mat-sidenav #sidenav [mode]="mode.value">
<p><button mat-button (click)="sidenav.toggle()">Toggle</button></p>
<p>
<mat-radio-group class="example-radio-group" [formControl]="mode">
<label>Mode:</label>
<mat-radio-button value="over">Over</mat-radio-button>
<mat-radio-button value="side">Side</mat-radio-button>
<mat-radio-button value="push">Push</mat-radio-button>
</mat-radio-group>
</p>
</mat-sidenav>
<mat-sidenav-content>
<p><button mat-button (click)="sidenav.toggle()">Toggle</button></p>
<p>
<mat-radio-group class="example-radio-group" [formControl]="mode">
<label>Mode:</label>
<mat-radio-button value="over">Over</mat-radio-button>
<mat-radio-button value="side">Side</mat-radio-button>
<mat-radio-button value="push">Push</mat-radio-button>
</mat-radio-group>
</p>
</mat-sidenav-content>
</mat-sidenav-container>
<div *ngIf="!shouldRun">Please open in Plunker to see result</div>
@@ -0,0 +1,14 @@
import {Component} from '@angular/core';
import {FormControl} from '@angular/forms';
/** @title Sidenav with configurable mode */
@Component({
selector: 'sidenav-mode-example',
templateUrl: 'sidenav-mode-example.html',
styleUrls: ['sidenav-mode-example.css'],
})
export class SidenavModeExample {
mode = new FormControl('over');
shouldRun = [/(^|\.)plnkr\.co$/, /(^|\.)stackblitz\.io$/].some(h => h.test(window.location.host));
}
@@ -0,0 +1,14 @@
.example-container {
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
}
.example-events {
width: 300px;
height: 200px;
overflow: auto;
border: 1px solid #555;
}
@@ -0,0 +1,17 @@
<mat-sidenav-container class="example-container" *ngIf="shouldRun">
<mat-sidenav #sidenav mode="side" [(opened)]="opened" (opened)="events.push('open!')"
(closed)="events.push('close!')">
Sidenav content
</mat-sidenav>
<mat-sidenav-content>
<p><mat-checkbox [(ngModel)]="opened">sidenav.opened</mat-checkbox></p>
<p><button mat-button (click)="sidenav.toggle()">sidenav.toggle()</button></p>
<p>Events:</p>
<div class="example-events">
<div *ngFor="let e of events">{{e}}</div>
</div>
</mat-sidenav-content>
</mat-sidenav-container>
<div *ngIf="!shouldRun">Please open in Plunker to see result</div>
@@ -0,0 +1,13 @@
import {Component} from '@angular/core';
/** @title Sidenav open & close behavior */
@Component({
selector: 'sidenav-open-close-example',
templateUrl: 'sidenav-open-close-example.html',
styleUrls: ['sidenav-open-close-example.css'],
})
export class SidenavOpenCloseExample {
events = [];
shouldRun = [/(^|\.)plnkr\.co$/, /(^|\.)stackblitz\.io$/].some(h => h.test(window.location.host));
}
@@ -1,16 +1,7 @@
.example-container {
width: 500px;
height: 300px;
border: 1px solid rgba(0, 0, 0, 0.5);
}
.example-sidenav-content {
display: flex;
height: 100%;
align-items: center;
justify-content: center;
}
.example-sidenav {
padding: 20px;
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
}
@@ -1,12 +1,6 @@
<mat-sidenav-container class="example-container">
<mat-sidenav #sidenav class="example-sidenav">
Jolly good!
</mat-sidenav>
<div class="example-sidenav-content">
<button type="button" mat-button (click)="sidenav.open()">
Open sidenav
</button>
</div>
<mat-sidenav-container class="example-container" *ngIf="shouldRun">
<mat-sidenav mode="side" opened="true">Sidenav content</mat-sidenav>
<mat-sidenav-content>Main content</mat-sidenav-content>
</mat-sidenav-container>
<div *ngIf="!shouldRun">Please open in Plunker to see result</div>
@@ -1,11 +1,11 @@
import {Component} from '@angular/core';
/**
* @title Basic sidenav
*/
/** @title Basic sidenav */
@Component({
selector: 'sidenav-overview-example',
templateUrl: 'sidenav-overview-example.html',
styleUrls: ['sidenav-overview-example.css'],
})
export class SidenavOverviewExample {}
export class SidenavOverviewExample {
shouldRun = [/(^|\.)plnkr\.co$/, /(^|\.)stackblitz\.io$/].some(h => h.test(window.location.host));
}
@@ -0,0 +1,7 @@
.example-container {
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
}
@@ -0,0 +1,7 @@
<mat-sidenav-container class="example-container" *ngIf="shouldRun">
<mat-sidenav opened mode="side">Start content</mat-sidenav>
<mat-sidenav opened mode="side" position="end">End content</mat-sidenav>
Implicit main content
</mat-sidenav-container>
<div *ngIf="!shouldRun">Please open in Plunker to see result</div>
@@ -0,0 +1,11 @@
import {Component} from '@angular/core';
/** @title Implicit main content with two sidenavs */
@Component({
selector: 'sidenav-position-example',
templateUrl: 'sidenav-position-example.html',
styleUrls: ['sidenav-position-example.css'],
})
export class SidenavPositionExample {
shouldRun = [/(^|\.)plnkr\.co$/, /(^|\.)stackblitz\.io$/].some(h => h.test(window.location.host));
}
@@ -0,0 +1,31 @@
.example-container {
display: flex;
flex-direction: column;
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
}
.example-is-mobile .example-toolbar {
position: fixed;
/* Make sure the toolbar will stay on top of the content as it scrolls past. */
z-index: 2;
}
h1.example-app-name {
margin-left: 8px;
}
.example-sidenav-container {
/* When the sidenav is not fixed, stretch the sidenav container to fill the available space. This
causes `<mat-sidenav-content>` to act as our scrolling element for desktop layouts. */
flex: 1;
}
.example-is-mobile .example-sidenav-container {
/* When the sidenav is fixed, don't constrain the height of the sidenav container. This allows the
`<body>` to be our scrolling element for mobile layouts. */
flex: 1 0 auto;
}
@@ -0,0 +1,22 @@
<div class="example-container" [class.example-is-mobile]="mobileQuery.matches" *ngIf="shouldRun">
<mat-toolbar color="primary" class="example-toolbar">
<button mat-icon-button (click)="snav.toggle()"><mat-icon>menu</mat-icon></button>
<h1 class="example-app-name">Responsive App</h1>
</mat-toolbar>
<mat-sidenav-container class="example-sidenav-container"
[style.marginTop.px]="mobileQuery.matches ? 56 : 0">
<mat-sidenav #snav [mode]="mobileQuery.matches ? 'over' : 'side'"
[fixedInViewport]="mobileQuery.matches" fixedTopGap="56">
<mat-nav-list>
<a mat-list-item routerLink="." *ngFor="let nav of fillerNav">{{nav}}</a>
</mat-nav-list>
</mat-sidenav>
<mat-sidenav-content>
<p *ngFor="let content of fillerContent">{{content}}</p>
</mat-sidenav-content>
</mat-sidenav-container>
</div>
<div *ngIf="!shouldRun">Please open in Plunker to see result</div>
@@ -0,0 +1,35 @@
import {MediaMatcher} from '@angular/cdk/layout';
import {ChangeDetectorRef, Component} from '@angular/core';
/** @title Responsive sidenav */
@Component({
selector: 'sidenav-responsive-example',
templateUrl: 'sidenav-responsive-example.html',
styleUrls: ['sidenav-responsive-example.css'],
})
export class SidenavResponsiveExample {
mobileQuery: MediaQueryList;
fillerNav = Array(50).fill(0).map((_, i) => `Nav Item ${i + 1}`);
fillerContent = Array(50).fill(0).map(() =>
`Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut
labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco
laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in
voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat
cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.`);
private _mobileQueryListener: () => void;
constructor(changeDetectorRef: ChangeDetectorRef, media: MediaMatcher) {
this.mobileQuery = media.matchMedia('(max-width: 600px)');
this._mobileQueryListener = () => changeDetectorRef.detectChanges();
this.mobileQuery.addListener(this._mobileQueryListener);
}
ngOnDestroy(): void {
this.mobileQuery.removeListener(this._mobileQueryListener);
}
shouldRun = [/(^|\.)plnkr\.co$/, /(^|\.)stackblitz\.io$/].some(h => h.test(window.location.host));
}