Skip to content

Commit 3315f32

Browse files
sgomestraviskaufman
authored andcommitted
feat(menu): Initial implementation of simple menus. (google#4835)
Only includes styles and basic functionality. Accessibility, auto-positioning, and focus trapping to come in a future PR. Part of google#4474 [#126819247]
1 parent af7beba commit 3315f32

19 files changed

+1424
-2
lines changed

demos/index.html

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
<li><a href="fab.html">FAB</a></li>
3636
<li><a href="icon-toggle.html">Icon Toggle</a></li>
3737
<li><a href="list.html">List</a></li>
38+
<li><a href="simple-menu.html">Menu (simple)</a></li>
3839
<li><a href="radio.html">Radio</a></li>
3940
<li><a href="ripple.html">Ripple</a></li>
4041
<li><a href="snackbar.html">Snackbar</a></li>

demos/simple-menu.html

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
<!DOCTYPE html>
2+
<!--
3+
Copyright 2016 Google Inc. All rights reserved.
4+
5+
Licensed under the Apache License, Version 2.0 (the "License");
6+
you may not use this file except in compliance with the License.
7+
You may obtain a copy of the License at
8+
9+
https://www.apache.org/licenses/LICENSE-2.0
10+
11+
Unless required by applicable law or agreed to in writing, software
12+
distributed under the License is distributed on an "AS IS" BASIS,
13+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
See the License for the specific language governing permissions and
15+
limitations under the License
16+
-->
17+
<html>
18+
<head>
19+
<meta charset="utf-8">
20+
<title>MDL Simple Menu Demo</title>
21+
<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1">
22+
<link href="https://fonts.googleapis.com/css?family=Roboto:300,400,500" rel="stylesheet">
23+
<link rel="stylesheet" href="https://fonts.googleapis.com/icon?family=Material+Icons">
24+
<script src="assets/material-design-lite.css.js" charset="utf-8"></script>
25+
<style>
26+
.demo-content {
27+
margin-top: 16px;
28+
height: 500px;
29+
width: 100%;
30+
background-color: antiquewhite;
31+
}
32+
</style>
33+
</head>
34+
<body>
35+
<main>
36+
<h1>MDL Simple Menu</h1>
37+
<label>
38+
<input type="radio" name="position" value="" checked>
39+
Top left
40+
</label>
41+
<label>
42+
<input type="radio" name="position" value="mdl-simple-menu--open-from-top-right">
43+
Top right
44+
</label>
45+
<label>
46+
<input type="radio" name="position" value="mdl-simple-menu--open-from-bottom-left">
47+
Bottom left
48+
</label>
49+
<label>
50+
<input type="radio" name="position" value="mdl-simple-menu--open-from-bottom-right">
51+
Bottom right
52+
</label>
53+
<div><button class="toggle">Toggle</button></div>
54+
<div class="mdl-simple-menu">
55+
<ul class="mdl-simple-menu__items mdl-list" role="menu" aria-hidden="true">
56+
<li class="mdl-list-item" role="menuitem" tabindex="0">Back</li>
57+
<li class="mdl-list-item" role="menuitem" tabindex="0">Forward</li>
58+
<li class="mdl-list-item" role="menuitem" tabindex="0">Reload</li>
59+
<li class="mdl-list-divider" role="separator"></li>
60+
61+
<li class="mdl-list-item" role="menuitem" tabindex="0">Save As...</li>
62+
<li class="mdl-list-item" role="menuitem" tabindex="0">Print...</li>
63+
<li class="mdl-list-item" role="menuitem" tabindex="0">Cast...</li>
64+
<li class="mdl-list-item" role="menuitem" tabindex="0">Translate to English</li>
65+
<li class="mdl-list-divider" role="separator"></li>
66+
67+
<li class="mdl-list-item" role="menuitem" tabindex="0">View Page Source</li>
68+
<li class="mdl-list-item" role="menuitem" tabindex="0">Inspect</li>
69+
</ul>
70+
</div>
71+
<div class="demo-content"></div>
72+
</main>
73+
74+
<script src="../assets/material-design-lite.js" charset="utf-8"></script>
75+
<script>
76+
var menu = new mdl.SimpleMenu(document.querySelector('.mdl-simple-menu'));
77+
document.querySelector('.toggle').addEventListener('click', function() {
78+
menu.open = !menu.open;
79+
});
80+
81+
var radios = document.querySelectorAll('input[name="position"]');
82+
for (var i = 0; i < radios.length; i++) {
83+
radios[i].addEventListener('change', function(evt) {
84+
if (evt.target.checked) {
85+
var menuEl = document.querySelector('.mdl-simple-menu');
86+
menuEl.classList.remove('mdl-simple-menu--open-from-top-right');
87+
menuEl.classList.remove('mdl-simple-menu--open-from-bottom-left');
88+
menuEl.classList.remove('mdl-simple-menu--open-from-bottom-right');
89+
if (evt.target.value) {
90+
menuEl.classList.add(evt.target.value);
91+
}
92+
}
93+
});
94+
}
95+
</script>
96+
</body>
97+
</html>

package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,8 +33,8 @@
3333
"cz-conventional-changelog": "^1.1.6",
3434
"del-cli": "^0.2.0",
3535
"dom-events": "^0.1.1",
36-
"eslint": "^2.12.0",
37-
"eslint-config-google": "^0.5.0",
36+
"eslint": "^3.6.1",
37+
"eslint-config-google": "^0.6.0",
3838
"eslint-plugin-tape": "^1.1.0",
3939
"extract-text-webpack-plugin": "^1.0.1",
4040
"ghooks": "^1.3.2",

packages/material-design-lite/index.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import * as ripple from 'mdl-ripple';
2222
import * as drawer from 'mdl-drawer';
2323
import * as textfield from 'mdl-textfield';
2424
import * as snackbar from 'mdl-snackbar';
25+
import * as menu from 'mdl-menu';
2526
import autoInit from 'mdl-auto-init';
2627

2728
// Register all components
@@ -32,6 +33,7 @@ autoInit.register('MDLIconToggle', iconToggle.MDLIconToggle);
3233
autoInit.register('MDLRadio', radio.MDLRadio);
3334
autoInit.register('MDLSnackbar', snackbar.MDLSnackbar);
3435
autoInit.register('MDLTextfield', textfield.MDLTextfield);
36+
autoInit.register('MDLSimpleMenu', menu.MDLSimpleMenu);
3537

3638
// Export all components.
3739
export {
@@ -43,5 +45,6 @@ export {
4345
snackbar,
4446
drawer,
4547
textfield,
48+
menu,
4649
autoInit
4750
};

packages/material-design-lite/material-design-lite.scss

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
@import "mdl-form-field/mdl-form-field";
2525
@import "mdl-icon-toggle/mdl-icon-toggle";
2626
@import "mdl-list/mdl-list";
27+
@import "mdl-menu/mdl-menu";
2728
@import "mdl-radio/mdl-radio";
2829
@import "mdl-ripple/mdl-ripple";
2930
@import "mdl-snackbar/mdl-snackbar";

packages/material-design-lite/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
"mdl-form-field": "^1.0.0",
1717
"mdl-icon-toggle": "^1.0.0",
1818
"mdl-list": "^1.0.0",
19+
"mdl-menu": "^1.0.0",
1920
"mdl-radio": "^1.0.0",
2021
"mdl-ripple": "^1.0.0",
2122
"mdl-snackbar": "^1.0.0",

packages/mdl-menu/README.md

Lines changed: 128 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,128 @@
1+
# MDL Menu
2+
3+
The MDL Menu component is a spec-aligned menu component adhering to the
4+
[Material Design menu specification](https://material.google.com/components/menus.html).
5+
It implements simple menus. Menus require JavaScript to work correctly, but the open and closed states are correct on
6+
first render.
7+
8+
## Installation
9+
10+
> Note: Installation via the npm registry will be available after alpha.
11+
12+
## Simple menu usage
13+
14+
A simple menu is usually closed, appearing when opened. It is appropriate for any display size.
15+
16+
```html
17+
<div class="mdl-simple-menu">
18+
<ul class="mdl-simple-menu__items mdl-list" role="menu">
19+
<li class="mdl-list-item" role="menuitem" tabindex="0">
20+
A Menu Item
21+
</li>
22+
<li class="mdl-list-item" role="menuitem" tabindex="0">
23+
Another Menu Item
24+
</li>
25+
</ul>
26+
</div>
27+
```
28+
29+
```js
30+
let menu = new mdl.SimpleMenu(document.querySelector('.mdl-simple-menu'));
31+
// Add event listener to some button to toggle the menu on and off.
32+
document.querySelector('.some-button').addEventListener('click', () => menu.open = !menu.open);
33+
```
34+
35+
You can start the menu in its open state by adding the `mdl-simple-menu--open` class to your HTML:
36+
37+
```html
38+
<div class="mdl-simple-menu mdl-simple-menu--open">
39+
...
40+
</div>
41+
```
42+
43+
44+
### Using the JS Component
45+
46+
MDL Simple Menu ships with a Component / Foundation combo which allows for frameworks to richly integrate the
47+
correct menu behaviors into idiomatic components.
48+
49+
The component has a read-write property, `open`, which keeps track of the visual state of the component.
50+
51+
```js
52+
// Analyse current state.
53+
console.log('The menu is ' + (menu.open ? 'open' : 'closed'));
54+
// Open menu.
55+
menu.open = true;
56+
// Close menu.
57+
menu.open = false;
58+
```
59+
60+
#### Including in code
61+
62+
##### ES2015
63+
64+
```javascript
65+
import {MDLSimpleMenu, MDLSimpleMenuFoundation} from 'mdl-menu';
66+
```
67+
68+
##### CommonJS
69+
70+
```javascript
71+
const mdlMenu = require('mdl-menu');
72+
const MDLSimpleMenu = mdlMenu.MDLSimpleMenu;
73+
const MDLSimpleMenuFoundation = mdlMenu.MDLSimpleMenuFoundation;
74+
```
75+
76+
##### AMD
77+
78+
```javascript
79+
require(['path/to/mdl-menu'], mdlMenu => {
80+
const MDLSimpleMenu = mdlMenu.MDLSimpleMenu;
81+
const MDLSimpleMenuFoundation = mdlMenu.MDLSimpleMenuFoundation;
82+
});
83+
```
84+
85+
##### Global
86+
87+
```javascript
88+
const MDLSimpleMenu = mdl.Menu.MDLSimpleMenu;
89+
const MDLSimpleMenuFoundation = mdl.Menu.MDLSimpleMenuFoundation;
90+
```
91+
92+
#### Automatic Instantiation
93+
94+
If you do not care about retaining the component instance for the simple menu, simply call `attachTo()` and pass it a
95+
DOM element.
96+
97+
```javascript
98+
mdl.MDLSimpleMenu.attachTo(document.querySelector('.mdl-simple-menu'));
99+
```
100+
101+
#### Manual Instantiation
102+
103+
Simple menus can easily be initialized using their default constructors as well, similar to `attachTo`.
104+
105+
```javascript
106+
import MDLSimpleMenu from 'mdl-menu';
107+
108+
const menu = new MDLSimpleMenu(document.querySelector('.mdl-simple-menu'));
109+
```
110+
111+
### Using the Foundation Class
112+
113+
MDL Simple Menu ships with an `MDLSimpleMenuFoundation` class that external frameworks and libraries can use to
114+
integrate the component. As with all foundation classes, an adapter object must be provided.
115+
The adapter for temporary drawers must provide the following functions, with correct signatures:
116+
117+
| Method Signature | Description |
118+
| --- | --- |
119+
| `addClass(className: string) => void` | Adds a class to the root element. |
120+
| `removeClass(className: string) => void` | Removes a class from the root element. |
121+
| `hasClass(className: string) => boolean` | Returns boolean indicating whether element has a given class. |
122+
| `hasNecessaryDom() => boolean` | Returns boolean indicating whether the necessary DOM is present (namely, the `mdl-temporary-drawer__drawer` drawer container). |
123+
| `getInnerDimensions() => {width: number, height: number}` | Returns an object with the items container width and height |
124+
| `setScale(x: string, y: string) => void` | Sets the transform on the root element to the provided (x, y) scale. |
125+
| `setInnerScale(x: string, y: string) => void` | Sets the transform on the items container to the provided (x, y) scale. |
126+
| `getNumberOfItems() => numbers` | Returns the number of elements inside the items container. |
127+
| `getYParamsForItemAtIndex(index: number) => {top: number, height: number}` | Returns an object with the offset top and offset height values for the element inside the items container at the provided index |
128+
| `setTransitionDelayForItemAtIndex(index: number, value: string) => void` | Sets the transition delay on the element inside the items container at the provided index to the provided value. |

packages/mdl-menu/index.js

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
/**
2+
* Copyright 2016 Google Inc. All Rights Reserved.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
export {MDLSimpleMenu, MDLSimpleMenuFoundation} from './simple';

packages/mdl-menu/mdl-menu.scss

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
/**
2+
* Copyright 2016 Google Inc. All Rights Reserved.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
@import "./simple/mdl-simple-menu";

packages/mdl-menu/package.json

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
{
2+
"name": "mdl-menu",
3+
"version": "1.0.0",
4+
"description": "The Material Design Lite menu component",
5+
"license": "Apache-2.0",
6+
"dependencies": {
7+
"mdl-animation": "^1.0.0",
8+
"mdl-base": "^1.0.0",
9+
"mdl-elevation": "^1.0.0",
10+
"mdl-theme": "^1.0.0",
11+
"mdl-typography": "^1.0.0"
12+
}
13+
}

packages/mdl-menu/simple/constants.js

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
/**
2+
* Copyright 2016 Google Inc. All Rights Reserved.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
const ROOT = 'mdl-simple-menu';
18+
19+
export const cssClasses = {
20+
ROOT,
21+
OPEN: `${ROOT}--open`,
22+
ANIMATING: `${ROOT}--animating`,
23+
TOP_RIGHT: `${ROOT}--open-from-top-right`,
24+
BOTTOM_LEFT: `${ROOT}--open-from-bottom-left`,
25+
BOTTOM_RIGHT: `${ROOT}--open-from-bottom-right`
26+
};
27+
28+
export const strings = {
29+
ITEMS_SELECTOR: `.${ROOT}__items`
30+
};
31+
32+
export const numbers = {
33+
// Total duration of the menu animation.
34+
TRANSITION_DURATION_MS: 300,
35+
// The menu starts its open animation with the X axis at this time value (0 - 1).
36+
TRANSITION_SCALE_ADJUSTMENT_X: 0.5,
37+
// The time value the menu waits until the animation starts on the Y axis (0 - 1).
38+
TRANSITION_SCALE_ADJUSTMENT_Y: 0.2,
39+
// The cubic bezier control points for the animation (cubic-bezier(0, 0, 0.2, 1)).
40+
TRANSITION_X1: 0,
41+
TRANSITION_Y1: 0,
42+
TRANSITION_X2: 0.2,
43+
TRANSITION_Y2: 1
44+
};

0 commit comments

Comments
 (0)