Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

docs(menu): add initial docs for menu #906

Merged
merged 1 commit into from
Jul 25, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
167 changes: 167 additions & 0 deletions src/components/menu/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,167 @@
# md-menu

`md-menu` is a list of options that displays when triggered. You can read more about menus in the
[Material Design spec](https://material.google.com/components/menus.html).

## Usage

### Setup

`md-menu` relies on the existence of an app-wide `OverlayContainer`. This is the container in which
it will display. You'll need to import this from `@angular2-material/core` and add it to your
providers list on bootstrap.

*main.ts*
```ts
import { OverlayContainer } from '@angular2-material/core';

bootstrap(AppComponent, [
OverlayContainer
]);
```

You'll also want to import the menu directives and add them to your component's directives array:

*my-comp.component.ts*
```ts
import {MD_MENU_DIRECTIVES} fom '@angular2-material/menu';

@Component({
...
directives: [MD_MENU_DIRECTIVES]
})
class MyComp {}
```

### Simple menu

In your template, create an `md-menu` element. You can use either `<button>` or `<anchor>` tags for
your menu items, as long as each is tagged with an `md-menu-item` attribute. Note that you can
disable items by adding the `disabled` boolean attribute or binding to it.

*my-comp.html*
```html
<!-- this menu starts as hidden by default -->
<md-menu>
<button md-menu-item> Refresh </button>
<button md-menu-item> Settings </button>
<button md-menu-item> Help </button>
<button md-menu-item disabled> Sign Out </button>
</md-menu>
```

Menus are hidden by default, so you'll want to connect up a menu trigger that can open your menu.
You can do so by adding a button tag with an `md-menu-trigger-for` attribute and passing in the menu
instance. You can create a local reference to your menu instance by adding `#menu="mdMenu"` to
your menu element.

*my-comp.html*
```html
<!-- menu opens when trigger button is clicked -->
<button md-icon-button [md-menu-trigger-for]="menu">
<md-icon>more_vert</md-icon>
</button>

<md-menu #menu="mdMenu">
<button md-menu-item> Refresh </button>
<button md-menu-item> Settings </button>
<button md-menu-item> Help </button>
<button md-menu-item disabled> Sign Out </button>
</md-menu>
```

Output:

<img src="https://material.angularjs.org/material2_assets/menu/default_closed.png">
<img src="https://material.angularjs.org/material2_assets/menu/default_open.png">

### Toggling the menu programmatically

You can also use the menu's API to open or close the menu programmatically from your class. Please
note that in this case, an `md-menu-trigger-for` attribute is still necessary to connect
the menu to its trigger element in the DOM.

*my-comp.component.ts*
```ts
class MyComp {
@ViewChild(MdMenuTrigger) trigger: MdMenuTrigger;

someMethod() {
this.trigger.openMenu();
}
}
```

*my-comp.html*
```html
<button md-icon-button [md-menu-trigger-for]="menu">
<md-icon>more_vert</md-icon>
</button>

<md-menu #menu="mdMenu">
<button md-menu-item> Refresh </button>
<button md-menu-item> Settings </button>
<button md-menu-item> Help </button>
<button md-menu-item disabled> Sign Out </button>
</md-menu>
```

### Customizing menu position

By default, the menu will display after and below its trigger. You can change this display position
using the `x-position` (`before | after`) and `y-position` (`above | below`) attributes.

*my-comp.html*
```html
<md-menu x-position="before" #menu="mdMenu">
<button md-menu-item> Refresh </button>
<button md-menu-item> Settings </button>
<button md-menu-item> Help </button>
<button md-menu-item disabled> Sign Out </button>
</md-menu>
```

Output:

<img src="https://material.angularjs.org/material2_assets/menu/before_closed.png">
<img src="https://material.angularjs.org/material2_assets/menu/before_open.png">

### Accessibility

The menu adds `role="menu"` to the main menu element and `role="menuitem"` to each menu item. It
also adds `aria-hasPopup="true"` to the trigger element.

### Menu attributes

| Signature | Values | Description |
| --- | --- | --- |
| `x-position` | `before | after` | The horizontal position of the menu in relation to the trigger. Defaults to `after`. |
| `y-position` | `above | below` | The vertical position of the menu in relation to the trigger. Defaults to `below`. |

### Trigger Programmatic API

**Properties**

| Name | Type | Description |
| --- | --- | --- |
| `menuOpen` | `Boolean` | Property that is true when the menu is open. It is not settable (use methods below). |
| `onMenuOpen` | `Observable<void>` | Observable that emits when the menu opens. |
| `onMenuClose` | `Observable<void>` | Observable that emits when the menu closes. |

**Methods**

| Method | Returns | Description |
| --- | --- | --- |
| `openMenu()` | `Promise<void>` | Opens the menu. Returns a promise that will resolve when the menu has opened. |
| `closeMenu()` | `Promise<void>` | Closes the menu. Returns a promise that will resolve when the menu has closed. |
| `toggleMenu()` | `Promise<void>` | Toggles the menu. Returns a promise that will resolve when the menu has completed opening or closing. |
| `destroyMenu()` | `Promise<void>` | Destroys the menu overlay completely.


### TODO

- Keyboard events: up arrow, down arrow, enter
- `prevent-close` option, to turn off automatic menu close when clicking outside the menu
- Custom offset support


15 changes: 10 additions & 5 deletions src/components/menu/menu-trigger.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ import {
export class MdMenuTrigger implements AfterViewInit, OnDestroy {
private _portal: TemplatePortal;
private _overlayRef: OverlayRef;
menuOpen: boolean = false;
private _menuOpen: boolean = false;

@Input('md-menu-trigger-for') menu: MdMenu;
@Output() onMenuOpen = new EventEmitter();
Expand All @@ -56,9 +56,11 @@ export class MdMenuTrigger implements AfterViewInit, OnDestroy {

ngOnDestroy() { this.destroyMenu(); }

get menuOpen(): boolean { return this._menuOpen; }

@HostListener('click')
toggleMenu(): Promise<void> {
return this.menuOpen ? this.closeMenu() : this.openMenu();
return this._menuOpen ? this.closeMenu() : this.openMenu();
}

openMenu(): Promise<void> {
Expand All @@ -75,14 +77,17 @@ export class MdMenuTrigger implements AfterViewInit, OnDestroy {
}

destroyMenu(): void {
if (this._overlayRef) { this._overlayRef.dispose(); }
if (this._overlayRef) {
this._overlayRef.dispose();
this._overlayRef = null;
}
}

// set state rather than toggle to support triggers sharing a menu
private _setIsMenuOpen(isOpen: boolean): void {
this.menuOpen = isOpen;
this._menuOpen = isOpen;
this.menu._setClickCatcher(isOpen);
this.menuOpen ? this.onMenuOpen.emit(null) : this.onMenuClose.emit(null);
this._menuOpen ? this.onMenuOpen.emit(null) : this.onMenuClose.emit(null);
}

/**
Expand Down