Project import generated by Copybara.

GitOrigin-RevId: 63746295f1a5ab5a619056791995793d65529e62
diff --git a/node_modules/mdl-ext/src/menu-button/_menu-button.scss b/node_modules/mdl-ext/src/menu-button/_menu-button.scss
new file mode 100644
index 0000000..9fd84d4
--- /dev/null
+++ b/node_modules/mdl-ext/src/menu-button/_menu-button.scss
@@ -0,0 +1,181 @@
+@charset "UTF-8";
+
+/**
+ * @license
+ * Copyright 2016 Leif Olsen. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * This code is built with Google Material Design Lite,
+ * which is Licensed under the Apache License, Version 2.0
+ */
+
+/* Moved to aria-expanded-toggle.scss
+
+.mdlext-aria-expanded-plus-minus {
+  @include mdlext-aria-expanded-toggle($font-family: inherit);
+}
+
+.mdlext-aria-expanded-more-less {
+  @include mdlext-aria-expanded-toggle($icon: 'expand_more', $icon-expanded: 'expand_less');
+}
+*/
+
+.mdlext-menu-button {
+  box-sizing: border-box;
+  @include typo-menu();
+  text-transform: none;
+  position: relative;
+  height: $button-height;
+  padding: 0 $button-padding;
+  display: flex;
+  align-items: center;
+  align-self: stretch;
+
+  > * {
+    margin: 0;
+    padding: 0 0 0 8px;
+  }
+
+  > *:first-child {
+    padding-left: 0;
+  }
+
+  > *:last-child:not(:only-child):not(.mdlext-menu__item__caption) {
+    margin-left: auto; // If more than one element, push last element to the right
+  }
+
+}
+
+.mdlext-menu-button__caption {
+  white-space: nowrap;
+  overflow: hidden;
+  text-overflow: ellipsis;
+  line-height: 1.2;
+}
+
+.mdlext-menu,
+.mdlext-menu__item {
+  box-sizing: border-box;
+  margin: 0;
+  padding: 0;
+  list-style: none;
+  display: flex;
+}
+
+.mdlext-menu {
+  position: absolute; //fixed;
+  background: $default-dropdown-bg-color;
+  z-index: 1000;
+  min-width: 124px;
+  border-radius: 2px;
+  @include shadow-3dp();
+  display: inline-flex;
+  flex-direction: column;
+  padding: 0;
+  overflow: hidden;
+  overflow-y: auto;
+
+  &:focus {
+    outline-offset: -1px;
+    outline-width: 1px;
+  }
+
+  &[hidden] {
+    @include mdlext-visually-hidden;
+    pointer-events: none;
+  }
+
+  &__item {
+    @include typo-body-1();
+    color: $default-item-text-color;
+    background-color: $default-dropdown-bg-color;
+    position: relative;
+    padding: 0 16px 0 24px;
+    align-items: center;
+    align-self: stretch;
+    text-decoration: none;
+    cursor: pointer;
+    white-space: nowrap;
+    user-select: none;
+    min-height: 40px;
+    overflow: hidden;
+
+    &[aria-selected='true'] {
+      background-color: $default-item-active-bg-color;
+    }
+
+    // checkmark
+    &[aria-selected='true']::before {
+      content:'\2713';
+      position: absolute;
+      font-size: 1.4em;
+      left: 4px;
+      top: 50%;
+      transform: translateY(-50%);
+      pointer-events: none;
+    }
+
+    &:hover:not([disabled]) {
+      background-color: $default-item-hover-bg-color;
+    }
+
+    &:focus {
+      outline-offset: -2px;
+      outline-width: 1px;
+      outline-color: $default-item-outline-color;
+      background-color: $default-item-focus-bg-color;
+    }
+
+    &::-moz-focus-inner {
+      border: 0;
+    }
+
+    &[disabled] {
+      color: $disabled-item-text-color;
+      background-color: transparent;
+      cursor: auto;
+      pointer-events: none;
+
+      > * {
+        color: $disabled-item-text-color;
+      }
+    }
+
+    &__caption {
+      white-space: nowrap;
+      overflow: hidden;
+      text-overflow: ellipsis;
+    }
+
+    > * {
+      margin: 0;
+      padding: 0 0 0 8px;
+    }
+
+    > *:first-child {
+      padding-left: 0;
+    }
+
+    > *:last-child:not(:only-child):not(.mdlext-menu__item__caption) {
+      margin-left: auto; // If more than one element, push last element to the right
+    }
+
+  }
+  &__item-separator {
+    margin: 0;
+    padding: 0;
+    border-bottom: 1px solid $default-item-divider-color;
+  }
+
+}
diff --git a/node_modules/mdl-ext/src/menu-button/menu-button.js b/node_modules/mdl-ext/src/menu-button/menu-button.js
new file mode 100644
index 0000000..e7e37d8
--- /dev/null
+++ b/node_modules/mdl-ext/src/menu-button/menu-button.js
@@ -0,0 +1,758 @@
+/**
+ * @license
+ * Copyright 2016 Leif Olsen. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * This code is built with Google Material Design Lite,
+ * which is Licensed under the Apache License, Version 2.0
+ */
+
+
+/**
+ * A menu button is a button that opens a menu. It is often styled as a
+ * typical push button with a downward pointing arrow or triangle to hint
+ * that activating the button will display a menu.
+ */
+import { randomString } from '../utils/string-utils';
+import fullThrottle from '../utils/full-throttle';
+import {
+  VK_TAB,
+  VK_ENTER,
+  VK_ESC,
+  VK_SPACE,
+  VK_END,
+  VK_HOME,
+  VK_ARROW_LEFT,
+  VK_ARROW_UP,
+  VK_ARROW_RIGHT,
+  VK_ARROW_DOWN,
+  IS_UPGRADED,
+} from '../utils/constants';
+
+import { getScrollParents, tether } from '../utils/dom-utils';
+
+const JS_MENU_BUTTON = 'mdlext-js-menu-button';
+const MENU_BUTTON_MENU = 'mdlext-menu';
+const MENU_BUTTON_MENU_ITEM = 'mdlext-menu__item';
+const MENU_BUTTON_MENU_ITEM_SEPARATOR = 'mdlext-menu__item-separator';
+//const MDL_LAYOUT_CONTENT = 'mdl-layout__content';
+
+/**
+ * Creates the menu controlled by the menu button
+ * @param element
+ * @return {{element: Element, selected: Element, open: (function(*=)), removeListeners: (function()), downgrade: (function())}}
+ */
+
+const menuFactory = element => {
+
+  let ariaControls = null;
+  let parentNode = null;
+
+  const removeAllSelected = () => {
+    [...element.querySelectorAll(`.${MENU_BUTTON_MENU_ITEM}[aria-selected="true"]`)]
+      .forEach(selectedItem => selectedItem.removeAttribute('aria-selected'));
+  };
+
+  const setSelected = (item, force=false) => {
+    if(force || (item && !item.hasAttribute('aria-selected'))) {
+      removeAllSelected();
+      if(item) {
+        item.setAttribute('aria-selected', 'true');
+      }
+    }
+  };
+
+  const getSelected = () => {
+    return element.querySelector(`.${MENU_BUTTON_MENU_ITEM}[aria-selected="true"]`);
+  };
+
+  const isDisabled = item => item && item.hasAttribute('disabled');
+
+  const isSeparator = item => item && item.classList.contains(MENU_BUTTON_MENU_ITEM_SEPARATOR);
+
+  const focus = item => {
+    if(item) {
+      item = item.closest(`.${MENU_BUTTON_MENU_ITEM}`);
+    }
+    if(item) {
+      item.focus();
+    }
+  };
+
+  const nextItem = current => {
+    let n = current.nextElementSibling;
+    if(!n) {
+      n = element.firstElementChild;
+    }
+    if(!isDisabled(n) && !isSeparator(n)) {
+      focus(n);
+    }
+    else {
+      let i = element.children.length;
+      while(n && i-- > 0) {
+        if(isDisabled(n) || isSeparator(n)) {
+          n = n.nextElementSibling;
+          if(!n) {
+            n = element.firstElementChild;
+          }
+        }
+        else {
+          focus(n);
+          break;
+        }
+      }
+    }
+  };
+
+  const previousItem = current => {
+    let p = current.previousElementSibling;
+    if(!p) {
+      p = element.lastElementChild;
+    }
+    if(!isDisabled(p) && !isSeparator(p)) {
+      focus(p);
+    }
+    else {
+      let i = element.children.length;
+      while(p && i-- > 0) {
+        if(isDisabled(p) || isSeparator(p)) {
+          p = p.previousElementSibling;
+          if(!p) {
+            p = element.lastElementChild;
+          }
+        }
+        else {
+          focus(p);
+          break;
+        }
+      }
+    }
+  };
+
+  const firstItem = () => {
+    const item = element.firstElementChild;
+    if(isDisabled(item) || isSeparator(item) ) {
+      nextItem(item);
+    }
+    else {
+      focus(item);
+    }
+  };
+
+  const lastItem = () => {
+    const item = element.lastElementChild;
+    if(isDisabled(item) || isSeparator(item)) {
+      previousItem(item);
+    }
+    else {
+      focus(item);
+    }
+  };
+
+  const selectItem = item => {
+    if(item && !isDisabled(item) && !isSeparator(item)) {
+      setSelected(item);
+      close(true, item);
+    }
+  };
+
+  const keyDownHandler = event => {
+
+    const item = event.target.closest(`.${MENU_BUTTON_MENU_ITEM}`);
+
+    switch (event.keyCode) {
+      case VK_ARROW_UP:
+      case VK_ARROW_LEFT:
+        if(item) {
+          previousItem(item);
+        }
+        else {
+          firstItem();
+        }
+        break;
+
+      case VK_ARROW_DOWN:
+      case VK_ARROW_RIGHT:
+        if(item) {
+          nextItem(item);
+        }
+        else {
+          lastItem();
+        }
+        break;
+
+      case VK_HOME:
+        firstItem();
+        break;
+
+      case VK_END:
+        lastItem();
+        break;
+
+      case VK_SPACE:
+      case VK_ENTER:
+        selectItem(item);
+        break;
+
+      case VK_ESC:
+        close(true);
+        break;
+
+      case VK_TAB:
+        // We do not have a "natural" tab order from menu, so the best we can do is to set focus back to the button
+        close(true);
+        break;
+
+      default:
+        return;
+    }
+    event.preventDefault();
+  };
+
+
+  const blurHandler = event => {
+
+    // See: https://github.com/facebook/react/issues/2011
+    const t = event.relatedTarget ||
+      event.explicitOriginalTarget || // FF
+      document.activeElement;         // IE11
+
+    //console.log('***** blur, target, relatedTarget', event.target, t);
+
+    try {
+      if (t) {
+        if (t.closest(`.${MENU_BUTTON_MENU}`) !== element && shouldClose(t)) {
+          close();
+        }
+      }
+      else {
+        close();
+      }
+    }
+    catch(err) {
+      // FF throws error: "TypeError: n.closest is not a function" if related target is a text node
+      close();
+    }
+  };
+
+  const clickHandler = event => {
+    //console.log('***** click, target', event.target);
+
+    event.preventDefault();
+    const t = event.target;
+    if (t && t.closest(`.${MENU_BUTTON_MENU}`) === element) {
+      const item = t.closest(`.${MENU_BUTTON_MENU_ITEM}`);
+      if (item) {
+        selectItem(item);
+      }
+    }
+    else {
+      if (shouldClose(t)) {
+        close();
+      }
+    }
+  };
+
+  const touchStartHandler = event => {
+    //console.log('***** touchStart, target', event.target);
+
+    const t = event.target;
+    if(!(t && t.closest(`.${MENU_BUTTON_MENU}`) === element)) {
+      if (event.type === 'touchstart') {
+        event.preventDefault();
+      }
+      close();
+    }
+  };
+
+  const addListeners = () => {
+    element.addEventListener('keydown', keyDownHandler, false);
+    element.addEventListener('blur', blurHandler, true);
+    element.addEventListener('click', clickHandler, true);
+    document.documentElement.addEventListener('touchstart', touchStartHandler, true);
+  };
+
+  const removeListeners = () => {
+    element.removeEventListener('keydown', keyDownHandler, false);
+    element.removeEventListener('blur', blurHandler, true);
+    element.removeEventListener('click', clickHandler, true);
+    document.documentElement.removeEventListener('touchstart', touchStartHandler, true);
+  };
+
+  const open = (controlElement, position='first') => {
+
+    ariaControls = controlElement.closest(`.${JS_MENU_BUTTON}`);
+
+    element.style['min-width'] = `${Math.max(124, controlElement.getBoundingClientRect().width)}px`;
+    element.removeAttribute('hidden');
+    tether(controlElement, element);
+
+    let item;
+    switch (position.toLowerCase()) {
+      case 'first':
+        firstItem();
+        break;
+
+      case 'last':
+        lastItem();
+        break;
+
+      case 'selected':
+        item = getSelected();
+        if(item && !item.hasAttribute('disabled')) {
+          focus(item);
+        }
+        else {
+          firstItem();
+        }
+        break;
+    }
+
+    addListeners();
+  };
+
+
+  const shouldClose = target => {
+    //console.log('***** shouldClose');
+
+    let result = false;
+    const btn = (target && target.closest(`.${JS_MENU_BUTTON}`)) || null;
+    if(!btn) {
+      result = true;
+    }
+    else if(btn.getAttribute('aria-controls') === element.id) {
+      if(btn !== ariaControls) {
+        result = true;
+      }
+    }
+    else {
+      result = true;
+    }
+    return result;
+  };
+
+  const close = (forceFocus = false, item = null) => {
+    removeListeners();
+
+    element.dispatchEvent(
+      new CustomEvent('_closemenu', {
+        bubbles: true,
+        cancelable: true,
+        detail: { forceFocus: forceFocus, item: item }
+      })
+    );
+  };
+
+  const addWaiAria = () => {
+    if (!element.hasAttribute('id')) {
+      // Generate a random id
+      element.id = `menu-button-${randomString()}`;
+    }
+    element.setAttribute('tabindex', '-1');
+    element.setAttribute('role', 'menu');
+    element.setAttribute('hidden', '');
+
+    [...element.querySelectorAll(`.${MENU_BUTTON_MENU_ITEM}`)].forEach( menuitem => {
+      menuitem.setAttribute('tabindex', '-1');
+      menuitem.setAttribute('role', 'menuitem');
+    });
+
+    [...element.querySelectorAll(`.${MENU_BUTTON_MENU_ITEM_SEPARATOR}`)].forEach( menuitem => {
+      menuitem.setAttribute('role', 'separator');
+    });
+  };
+
+  const init = () => {
+    addWaiAria();
+    parentNode = element.parentNode;
+    element.classList.add('is-upgraded');
+  };
+
+  const downgrade = () => {
+    removeListeners();
+    if(element.parentNode !== parentNode) {
+      parentNode.appendChild(element);
+    }
+    element.classList.remove('is-upgraded');
+  };
+
+  init();
+
+  return {
+    /**
+     * Get the menu element
+     * @returns {Element} the menu element
+     */
+    get element() {
+      return element;
+    },
+
+    /**
+     * Set selected menu item
+     * @param item
+     */
+    set selected(item) {
+      setSelected(item, true);
+    },
+
+    /**
+     * Open menu
+     * @param {Element} controlElement the element where the menu should be aligned to
+     * @param {String} position menuElement item to receive focus after menu element is opened
+     */
+    open: (controlElement, position='first') => open(controlElement, position),
+
+    /**
+     * Remove event listeners.
+     */
+    removeListeners: () => removeListeners(),
+
+    /**
+     * Downgrade menu
+     */
+    downgrade: () => downgrade(),
+  };
+};
+
+
+/**
+ * The menubutton component
+ */
+
+class MenuButton {
+
+  constructor(element) {
+    this.element = element;
+    this.focusElement = undefined;
+    this.focusElementLastScrollPosition = undefined;
+    this.scrollElements = [];
+    this.menu = undefined;
+    this.selectedItem = null;
+    this.init();
+  }
+
+  keyDownHandler = event => {
+    if(!this.isDisabled()) {
+      switch (event.keyCode) {
+        case VK_ARROW_UP:
+          this.openMenu('last');
+          break;
+
+        case VK_ARROW_DOWN:
+          this.openMenu();
+          break;
+
+        case VK_SPACE:
+        case VK_ENTER:
+          this.openMenu('selected');
+          break;
+
+        case VK_ESC:
+          this.closeMenu();
+          break;
+
+        case VK_TAB:
+          this.closeMenu();
+          return;
+
+        default:
+          return;
+      }
+    }
+    //event.stopPropagation();
+    event.preventDefault();
+  };
+
+  clickHandler = () => {
+    if(!this.isDisabled()) {
+      if(this.element.getAttribute('aria-expanded').toLowerCase() === 'true') {
+        this.closeMenu(true);
+      }
+      else {
+        this.openMenu('selected');
+      }
+    }
+  };
+
+  /**
+   * Re-position menu if content is scrolled, window is resized or orientation change
+   * @see https://javascriptweblog.wordpress.com/2015/11/02/of-classes-and-arrow-functions-a-cautionary-tale/
+   */
+  recalcMenuPosition = fullThrottle( () => {
+    const c = this.focusElement.getBoundingClientRect();
+    const dx = this.focusElementLastScrollPosition.left - c.left;
+    const dy = this.focusElementLastScrollPosition.top - c.top;
+    const left = (parseFloat(this.menu.element.style.left) || 0) - dx;
+    const top = (parseFloat(this.menu.element.style.top) || 0) - dy;
+
+    this.menu.element.style.left = `${left}px`;
+    this.menu.element.style.top = `${top}px`;
+    this.focusElementLastScrollPosition = c;
+  });
+
+
+  positionChangeHandler = () => {
+    this.recalcMenuPosition(this);
+  };
+
+  closeMenuHandler = event => {
+    if(event && event.detail) {
+      if(event.detail.item && event.detail.item !== this.selectedItem) {
+        this.selectedItem = event.detail.item;
+        this.dispatchMenuSelect();
+      }
+      this.closeMenu(event.detail.forceFocus);
+    }
+  };
+
+  dispatchMenuSelect() {
+    this.element.dispatchEvent(
+      new CustomEvent('menuselect', {
+        bubbles: true,
+        cancelable: true,
+        detail: { source: this.selectedItem }
+      })
+    );
+  }
+
+  isDisabled() {
+    return this.element.hasAttribute('disabled');
+  }
+
+  removeListeners() {
+    this.element.removeEventListener('keydown', this.keyDownHandler);
+    this.element.removeEventListener('click', this.clickHandler);
+  }
+
+  openMenu(position='first') {
+
+    if(!this.isDisabled() && this.menu) {
+
+      // Close the menu if button position change
+      this.scrollElements = getScrollParents(this.element);
+      this.scrollElements.forEach(el => el.addEventListener('scroll', this.positionChangeHandler));
+
+      window.addEventListener('resize', this.positionChangeHandler);
+      window.addEventListener('orientationchange', this.positionChangeHandler);
+      this.menu.element.addEventListener('_closemenu', this.closeMenuHandler);
+
+      this.menu.selected = this.selectedItem;
+      this.menu.open(this.focusElement, position);
+      this.element.setAttribute('aria-expanded', 'true');
+
+      this.focusElementLastScrollPosition = this.focusElement.getBoundingClientRect();
+    }
+  }
+
+  closeMenu(forceFocus = false) {
+    if(this.menu) {
+      this.menu.removeListeners();
+      this.scrollElements.forEach(el => el.removeEventListener('scroll', this.positionChangeHandler));
+      window.removeEventListener('resize', this.positionChangeHandler);
+      window.removeEventListener('orientationchange', this.positionChangeHandler);
+      this.menu.element.removeEventListener('_closemenu', this.closeMenuHandler);
+
+      if (forceFocus) {
+        this.focus();
+      }
+      this.element.setAttribute('aria-expanded', 'false');
+      this.menu.element.setAttribute('hidden', '');
+    }
+  }
+
+  focus() {
+    if(!this.isDisabled()) {
+      this.focusElement.focus();
+    }
+  }
+
+  init() {
+    const addListeners = () => {
+      this.element.addEventListener('keydown', this.keyDownHandler);
+      this.element.addEventListener('click', this.clickHandler);
+    };
+
+    const addWaiAria = () => {
+      this.element.setAttribute('role', 'button');
+      this.element.setAttribute('aria-expanded', 'false');
+      this.element.setAttribute('aria-haspopup', 'true');
+    };
+
+    const addFocusElement = () => {
+      this.focusElement = this.element.querySelector('input[type="text"]');
+      if(!this.focusElement) {
+        this.focusElement = this.element;
+
+        if(!(this.focusElement.tagName.toLowerCase() === 'button' || this.focusElement.tagName.toLowerCase() === 'input')) {
+          if (!this.focusElement.hasAttribute('tabindex')) {
+            this.focusElement.setAttribute('tabindex', '0');
+          }
+        }
+      }
+    };
+
+    const moveElementToDocumentBody = (element) => {
+      // To position an element on top of all other z-indexed elements, the element should be moved to document.body
+      //       See: https://philipwalton.com/articles/what-no-one-told-you-about-z-index/
+
+      if(element.parentNode !== document.body) {
+        return document.body.appendChild(element);
+      }
+      return element;
+    };
+
+    const findMenuElement = () => {
+      let menuElement;
+      const menuElementId = this.element.getAttribute('aria-controls');
+      if(menuElementId !== null) {
+        menuElement = document.querySelector(`#${menuElementId }`);
+      }
+      else {
+        menuElement = this.element.parentNode.querySelector(`.${MENU_BUTTON_MENU}`);
+      }
+      return menuElement;
+    };
+
+    const addMenu = () => {
+      const menuElement = findMenuElement();
+      if(menuElement) {
+        if(menuElement.componentInstance) {
+          this.menu = menuElement.componentInstance;
+        }
+        else {
+          this.menu = menuFactory(menuElement);
+          menuElement.componentInstance = this.menu;
+          moveElementToDocumentBody(menuElement);
+        }
+        this.element.setAttribute('aria-controls', this.menu.element.id);
+      }
+    };
+
+    addFocusElement();
+    addWaiAria();
+    addMenu();
+    this.removeListeners();
+    addListeners();
+  }
+
+  downgrade() {
+    if(this.menu) {
+      // Do not downgrade menu if there are other buttons sharing this menu
+      const related = [...document.querySelectorAll(`.${JS_MENU_BUTTON}[aria-controls="${this.element.getAttribute('aria-controls')}"]`)];
+      if(related.filter( c => c !== this.element && c.getAttribute('data-upgraded').indexOf('MaterialExtMenuButton') >= 0).length === 0) {
+        this.menu.downgrade();
+      }
+    }
+    this.removeListeners();
+  }
+
+}
+
+(function() {
+  'use strict';
+
+  /**
+   * https://github.com/google/material-design-lite/issues/4205
+   * @constructor
+   * @param {Element} element The element that will be upgraded.
+   */
+  const MaterialExtMenuButton = function MaterialExtMenuButton(element) {
+    this.element_ = element;
+    this.menuButton_ = null;
+
+    // Initialize instance.
+    this.init();
+  };
+  window['MaterialExtMenuButton'] = MaterialExtMenuButton;
+
+
+  // Public methods.
+
+  /**
+   * Get the menu element controlled by this button, null if no menu is controlled by this button
+   * @public
+   */
+  MaterialExtMenuButton.prototype.getMenuElement = function() {
+    return this.menuButton_.menu ? this.menuButton_.menu.element : null;
+  };
+  MaterialExtMenuButton.prototype['getMenuElement'] = MaterialExtMenuButton.prototype.getMenuElement;
+
+  /**
+   * Open menu
+   * @public
+   * @param {String} position one of "first", "last" or "selected"
+   */
+  MaterialExtMenuButton.prototype.openMenu = function(position) {
+    this.menuButton_.openMenu(position);
+  };
+  MaterialExtMenuButton.prototype['openMenu'] = MaterialExtMenuButton.prototype.openMenu;
+
+  /**
+   * Close menu
+   * @public
+   */
+  MaterialExtMenuButton.prototype.closeMenu = function() {
+    this.menuButton_.closeMenu(true);
+  };
+  MaterialExtMenuButton.prototype['closeMenu'] = MaterialExtMenuButton.prototype.closeMenu;
+
+  /**
+   * Get selected menu item
+   * @public
+   * @returns {Element} The selected menu item or null if no item selected
+   */
+  MaterialExtMenuButton.prototype.getSelectedMenuItem = function() {
+    return this.menuButton_.selectedItem;
+  };
+  MaterialExtMenuButton.prototype['getSelectedMenuItem'] = MaterialExtMenuButton.prototype.getSelectedMenuItem;
+
+
+  /**
+   * Set (default) selected menu item
+   * @param {Element} item
+   */
+  MaterialExtMenuButton.prototype.setSelectedMenuItem = function(item) {
+    this.menuButton_.selectedItem = item;
+  };
+  MaterialExtMenuButton.prototype['setSelectedMenuItem'] = MaterialExtMenuButton.prototype.setSelectedMenuItem;
+
+  /**
+   * Initialize component
+   */
+  MaterialExtMenuButton.prototype.init = function() {
+    if (this.element_) {
+      this.menuButton_ = new MenuButton(this.element_);
+      this.element_.addEventListener('mdl-componentdowngraded', this.mdlDowngrade_.bind(this));
+      this.element_.classList.add(IS_UPGRADED);
+    }
+  };
+
+  /**
+   * Downgrade component
+   * E.g remove listeners and clean up resources
+   */
+  MaterialExtMenuButton.prototype.mdlDowngrade_ = function() {
+    this.menuButton_.downgrade();
+  };
+
+  // The component registers itself. It can assume componentHandler is available
+  // in the global scope.
+  /* eslint no-undef: 0 */
+  componentHandler.register({
+    constructor: MaterialExtMenuButton,
+    classAsString: 'MaterialExtMenuButton',
+    cssClass: JS_MENU_BUTTON,
+    widget: true
+  });
+})();
diff --git a/node_modules/mdl-ext/src/menu-button/readme.md b/node_modules/mdl-ext/src/menu-button/readme.md
new file mode 100644
index 0000000..ab3a219
--- /dev/null
+++ b/node_modules/mdl-ext/src/menu-button/readme.md
@@ -0,0 +1,472 @@
+# Menu Button
+![Menu button](../../etc/menu-button.png)     ![Menu button](../../etc/menu-button-2.png)
+
+A WAI-ARIA friendly menu button component/widget with roles, attributes and behavior in accordance with the specification 
+given in WAI-ARIA Authoring Practices, [section 2.20](https://www.w3.org/TR/wai-aria-practices/#button).
+
+## Introduction
+A menu button is a button that opens a menu. It is often styled as a typical push button with a 
+downward pointing arrow or triangle to hint that activating the button will display a menu. 
+
+A menu is a widget that offers a list of choices to the user, such as a set of actions or functions. A menu is (usually) 
+opened, or made visible, by activating a menu button. When a user activates a choice in a menu, the menu (usually) closes.
+
+In this release a `<button>`, an `<input type="text">` or a `<div>` (mdl-textfield) can have `role="button"`, and act as 
+the control for a menu. 
+
+## To include a MDLEXT **menu button** component:
+
+&nbsp;1. Code a `<button>` element; this is the clickable toggle that will show and hide the menu. Include an `aria-controls` 
+attribute whose value will match the id attribute of the unordered list coded in the next step. Inside the button, 
+code a `<span>` element to hold the button caption text and a `<i>` element to contain a state icon.
+
+```html
+<button aria-controls="menu1">
+  <span></span>
+  <i></i>
+</button>
+```
+
+&nbsp;2. Code a `<ul>` unordered list element; this is the container that holds the menu choices. Include an id attribute 
+whose value will match the `aria-controls` attribute of the button element.
+
+```html
+<ul id="menu1">
+</ul>
+```
+
+&nbsp;3. Inside the unordered list, code one `<li>` element for each choice. Add a text caption as appropriate.
+
+```html
+<ul id="menu1">
+  <li>Small</li>
+  <li>Medium</li>
+  <li>Large</li>
+</ul>
+```
+
+&nbsp;4. Add one or more MDL classes, separated by spaces, to the button, span and i elements using the class attribute.
+
+```html
+<button class="mdl-button mdl-js-button" aria-controls="menu1">
+  <span>Select a value</span>
+  <i class="material-icons">more_vert</i>
+</button>
+```
+
+&nbsp;5. Add the `mdlext-js-menu-button` class to define the element as a menu button component.
+
+```html
+<button class="mdl-button mdl-js-button mdlext-js-menu-button" aria-controls="menu1">
+  <span>Select a value</span>
+  <i class="material-icons">more_vert</i>
+</button>
+```
+
+&nbsp;6. Add the `mdlext-menu` class to the unordered list and the `mdlext-menu__item` class to the list items. 
+
+```html
+<ul id="menu1" class="mdlext-menu">
+  <li class="mdlext-menu__item">Small</li>
+  <li class="mdlext-menu__item">Medium</li>
+  <li class="mdlext-menu__item">Large</li>
+</ul>
+```
+
+The menu button component is ready for use.
+
+>**Note:** After page load, the component will add all required Aria roles and attributes.
+
+```html
+<button class="mdl-button mdl-js-button mdlext-js-menu-button" 
+  role="button" aria-expanded="false" aria-haspopup="true" aria-controls="menu1">
+  <span>Select a value</span>
+  <i class="material-icons">more_vert</i>
+</button>
+<ul  id="menu1" class="mdlext-menu" role="menu" tabindex="-1" hidden>
+  <li class="mdlext-menu__item" role="menuitem" tabindex="-1">Small</li>
+  <li class="mdlext-menu__item" role="menuitem" tabindex="-1">Medium</li>
+  <li class="mdlext-menu__item" role="menuitem" tabindex="-1">Large</li>
+</ul>
+```
+
+
+### Examples
+
+**A menu button with three options.**
+
+```html
+<button class="mdl-button mdl-js-button mdlext-js-menu-button" aria-controls="menu1">
+  <span>Select a value</span>
+  <i class="material-icons">more_vert</i>
+</button>
+<ul id="menu1" class="mdlext-menu">
+  <li class="mdlext-menu__item">Small</li>
+  <li class="mdlext-menu__item">Medium</li>
+  <li class="mdlext-menu__item">Large</li>
+</ul>
+```
+
+> **Note:** If the button and the menu has a common ancestor element, the `aria-controls` attribute of the button and 
+the `id` attribute of the menu may be skipped.
+
+```html
+<div role="presentation">
+  <button class="mdl-button mdl-js-button mdlext-js-menu-button">
+    <span>Select a value</span>
+    <i class="material-icons">more_vert</i>
+  </button>
+  <ul class="mdlext-menu">
+    <li class="mdlext-menu__item">Small</li>
+    <li class="mdlext-menu__item">Medium</li>
+    <li class="mdlext-menu__item">Large</li>
+  </ul>
+</div>
+```
+
+With this markup the component will generate a random `id` attribute for the menu and associate it with the `aria-controls` 
+of the button.
+
+
+**A menu button with a select listener. Uses a data-value attribute to pass the actual value.**
+
+```html
+<div>
+  <button id="my-button" class="mdl-button mdl-js-button mdl-button--icon mdl-button--primary mdlext-js-menu-button"
+    onmenuselect="document.querySelector('#selection').innerHTML = 'Selected value: ' + event.detail.source.getAttribute('data-value');">
+    <span>Select</span>
+    <i class="mdlext-aria-expanded-more-less"></i>
+  </button>
+  <ul class="mdlext-menu" hidden >
+    <li class="mdlext-menu__item" data-value="10">Ten</li>
+    <li class="mdlext-menu__item" data-value="25">Twentyfive</li>
+    <li class="mdlext-menu__item" data-value="50">Fifty</li>
+  </ul>
+</div>
+```
+```javascript
+document.querySelector('#my-button').addEventListener('menuselect', function(event) {
+  this.querySelector('span').innerHTML = 'Selected value: ' + 
+    event.detail.source.getAttribute('data-value')
+});
+```
+
+
+**A menu button decorated with icons**
+
+```html
+<style>
+.material-icons.md-18 {
+   font-size: 18px;
+}
+</style>
+
+<button class="mdl-button mdl-button--raised mdl-js-ripple-effect mdl-js-button mdlext-js-menu-button"
+  aria-controls="demo-menu">
+  <i class="material-icons">gesture</i>
+  <span class="mdlext-menu-button__caption">Select</span>
+  <i class="material-icons mdlext-aria-expanded-more-less"></i>
+</button>
+
+<ul id="demo-menu" class="mdlext-menu" hidden>
+  <li class="mdlext-menu__item">
+    <i class="material-icons md-18">info</i>
+    <span class="mdlext-menu__item__caption">Menu item #1</span>
+  </li>
+  <li class="mdlext-menu__item">
+    <i class="material-icons md-18">help_outline</i>
+    <span class="mdlext-menu__item__caption">Menu item #2. A long text to check ellipsis overflow 0123456789</span>
+    <i class="material-icons md-18">radio</i>
+  </li>
+  <li class="mdlext-menu__item-separator"></li>
+  <li class="mdlext-menu__item" disabled>
+    <span class="mdlext-menu__item__caption">Menu item #3, disabled</span>
+    <i class="material-icons md-18">accessibility</i>
+  </li>
+  <li class="mdlext-menu__item-separator"></li>
+  <li class="mdlext-menu__item">
+    <span class="mdlext-menu__item__caption">Menu item #IV</span>
+    <i class="material-icons md-18">build</i>
+  </li>
+  <li class="mdlext-menu__item">
+    <span class="mdlext-menu__item__caption">Menu item #V</span>
+    <i class="material-icons md-18">build</i>
+  </li>
+  <li class="mdlext-menu__item-separator"></li>
+  <li class="mdlext-menu__item">
+    <span class="mdlext-menu__item__caption">Menu item #VI</span>
+    <i class="material-icons md-18">build</i>
+  </li>
+  <li class="mdlext-menu__item">
+    <span class="mdlext-menu__item__caption">Menu item #VII</span>
+    <i class="material-icons md-18">build</i>
+  </li>
+  <li class="mdlext-menu__item">
+    Menu item #n
+  </li>
+</ul>
+```
+
+**A mdl-textfield component can be used as a menu button.**
+
+```html
+<style>
+  .mdl-textfield.mdlext-js-menu-button .mdl-textfield__input {
+    padding-right: 40px;
+  }
+  .mdl-textfield__icon {
+    width: 32px;
+    text-align: left;
+    position: absolute;
+    right: 0;
+    top: 50%;
+    transform: translateY(-50%);
+  }
+  .mdl-textfield.is-disabled .mdl-textfield__icon {
+    color: rgba(0, 0, 0, 0.26) !important;
+  }
+  .mdl-textfield.is-invalid .mdl-textfield__icon {
+    color: #de3226 !important;
+  }
+</style>
+
+<div role="presentation">
+  <div id="my-textfield" class="mdl-textfield mdl-js-textfield mdlext-js-menu-button">
+    <input class="mdl-textfield__input" type="text" readonly>
+    <label class="mdl-textfield__label">Sign in with ...</label>
+    <i class="material-icons mdl-textfield__icon mdlext-aria-expanded-more-less"></i>
+  </div>
+  <ul class="mdlext-menu" hidden >
+    <li class="mdlext-menu__item" data-key="S">Small</li>
+    <li class="mdlext-menu__item" data-key="M">Medium</li>
+    <li class="mdlext-menu__item" data-key="L">Large</li>
+  </ul>
+</div>
+```
+```javascript
+document.querySelector('#my-textfield').addEventListener('menuselect', function(event) {
+  this.MaterialTextfield.change(event.detail.source.getAttribute('data-key') 
+           + ': ' + event.detail.source.querySelector('span').innerHTML);
+});
+```
+
+**Create your own state icon with SASS.**
+The [_mixins.scss](../_mixins.scss) has a mixin which can be used to create custom state icons.  
+
+```sass
+@charset "UTF-8";
+.my-aria-expanded-state {
+  @include mdlext-aria-expanded-toggle($icon: 'arrow_downward', $icon-expanded: 'arrow_upward');
+}
+```
+
+**Use a custom styled `div` as a menu button.**
+
+```html
+<div role="presentation">
+  <div id="my-div" class="mdlext-menu-button mdlext-js-menu-button" 
+       style="width:300px; height:44px; max-width:100%; border:1px solid green">
+       
+    <span class="mdlext-menu-button__caption">Select a size ...</span>
+    <i class="material-icons my-aria-expanded-state"></i>
+  </div>
+  <ul class="mdlext-menu" hidden >
+    <li class="mdlext-menu__item" data-key="S">Small</li>
+    <li class="mdlext-menu__item" data-key="M">Medium</li>
+    <li class="mdlext-menu__item" data-key="L">Large</li>
+  </ul>
+</div>
+```
+```javascript
+document.querySelector('#my-div').addEventListener('menuselect', function(event) {
+  this.querySelector('span').innerHTML = 
+     event.detail.source.getAttribute('data-key') + ': ' + 
+     event.detail.source.querySelector('span').innerHTML);
+});
+```
+
+**Many buttons can share one menu.**
+
+```html
+<button class="mdl-button mdl-js-button mdlext-js-menu-button" aria-controls="shared-menu">
+  <span class="mdlext-menu-button__caption">A button</span>
+</button>
+
+<div class="mdl-textfield mdl-js-textfield mdlext-js-menu-button" aria-controls="shared-menu">
+  <input class="mdl-textfield__input" type="text" readonly>
+  <label class="mdl-textfield__label">A MDL textfield</label>
+</div>
+
+<ul id="shared-menu" class="mdlext-menu" hidden>
+  <li class="mdlext-menu__item" role="menuitem">Menu item #1</li>
+  <li class="mdlext-menu__item" role="menuitem">Menu item #2</li>
+  <li class="mdlext-menu__item" role="menuitem">Menu item #n</li>
+</ul>
+```
+
+
+### More examples
+* The [snippets/menu-button.html](./snippets/menu-button.html) and the [tests](../../test/menu-button/menu-button.spec.js) provides more detailed examples.
+* Try out the [live demo](http://leifoolsen.github.io/mdl-ext/demo/menu-button.html)
+
+
+## Characteristics
+
+### Keyboard interaction, Menu Button 
+* With focus on the button:
+    * <kbd>Space</kbd> or <kbd>Enter</kbd>: opens the menu, sets `aria-expanded="true"`, and place focus on the previously selected menu item - or on the first menu item if no selected menu item.
+    * <kbd>Down Arrow</kbd>: opens the menu, sets `aria-expanded="true"`, and moves focus to the first menu item.
+    * <kbd>Up Arrow</kbd>: opens the menu, sets `aria-expanded="true"`, and moves focus to the last menu item.
+
+### Mouse interaction, Menu Button 
+* With focus on the button:
+    * <kbd>Click</kbd>: opens the menu, sets `aria-expanded="true"`, and place focus on the previously selected menu item - or on the first menu item if no selected menu item.
+    * <kbd>Click</kbd>: a second click closes the menu, sets `aria-expanded="false"` and place focus on button.
+    
+### Keyboard interaction, Menu
+* With focus on the menu:
+    * <kbd>Space</kbd> or <kbd>Enter</kbd>: sets `aria-selected="true"` on active menu item, sets `aria-expanded="true"` on menu button, closes menu and moves focus back to menu button. The button emits a custom `select` event with a referfence to the selected menu element.
+    * <kbd>Home</kbd>: move focus to first menu item.
+    * <kbd>End</kbd>: move focus to last menu item.
+    * <kbd>Up Arrow</kbd> or <kbd>Left Arrow</kbd>: move focus to previous menu item.
+    * <kbd>Down Arrow</kbd> or <kbd>Right Arrow</kbd>: Move focus to next menu item.
+    * <kbd>Esc</kbd>: Closes the menu, sets `aria-expanded="true"` on menu button, and move focus back to menu button.
+
+>The keyboard behavior after the menu is open are described in more detail in WAI-ARIA Authoring Practices, [2.19 Menu or Menu bar](https://www.w3.org/TR/wai-aria-practices/#menu).
+
+### Mouse interaction, Menu
+* With focus on the menu:
+    * <kbd>Click</kbd>: sets `aria-selected="true"` on active menu item, sets `aria-expanded="true"` on menu button, closes menu and moves focus back to menu button. The button emits a custom `select` event with a referfence to the selected menu element. 
+
+## WAI-ARIA Roles, States, and Properties
+The menu button has the following roles, states and properties set by the menu button component.
+
+### Menu Button
+* `role="button"`: the element that opens the menu has role [button](http://www.w3.org/TR/wai-aria-1.1/#button).
+* `aria-haspopup`: the element with role `button` has [aria-haspopup](http://www.w3.org/TR/wai-aria-1.1/#aria-haspopup) set to `true`.
+* `aria-controls`: identfies the content on the page (e.g. using IDREFs) that this menu button controls.
+* `aria-expanded`: the element with role `button` has [aria-expanded](https://www.w3.org/TR/wai-aria-1.1/#aria-expanded) set to `true` if the corresponding menu is open, oterwise false.
+* `aria-expanded`: when a menu item is disabled, `aria-disabled` is set to `true`.
+* `disabled"`: indicates that a button is disabled, otherwise not present.
+
+### Menu, WAI-ARIA Roles
+* `role="menu"`: identifies the element as a menu widget.
+* `hidden`: the menu has attrubute hidden if the controlling buttoun has `aria-expanded="false"`, otherwise the attribute is not present.
+* `role="menuitem"`: identifies an element as a menu item widget.
+* `role="menuitemcheckbox"`: (not yet implemented).
+* `role="menuitemradion"`: (not yet implemented).
+* `aria-selected`: the selected menu item has `aria-selected="true"`, otherwise not present.
+* `role="separator"`: a divider that separates and distinguishes sections of content or groups of menuitems..
+* `disabled"`: indicates that a menu item is disabled, otherwise not present.
+
+ 
+>The roles, states, and properties needed for the menu are described in more detail in WAI-ARIA Authoring Practices, [2.19 Menu or Menu bar](https://www.w3.org/TR/wai-aria-practices/#menu).
+
+## Events emitted from the component
+The menu button emits a custom `menuselect` event when a menu item is selected. The event has a detail object with the following structure:
+
+```javascript
+detail: { 
+  source: item // The selected menu item 
+}
+```
+
+To set up an event listener to receive the select custom event.
+```javascript
+document.querySelector('#my-menubutton').addEventListener('menuselect', function(e) {
+  console.log('menu item selected:', e.detail.source);
+});
+```
+Refer to [snippets/menu-button.html](./snippets/menu-button.html) or the [tests](../../test/menu-button/menu-button.spec.js) for detailed usage.
+
+
+## Public methods
+
+### openMenu(position)
+Open menu at given position. Position is on of `first`, `last` or `selected`. Default value is `first`.
+* `first` focus first menu item
+* `last` focus last menu item
+* `selected` focus previously selected menu item
+
+```javascript
+const menuButton = document.querySelector('#my-menu-button');
+menuButton.MaterialExtMenuButton.openMenu();
+```
+
+### closeMenu()
+Closes an open menu. Moves focus to button.
+
+```javascript
+const menuButton = document.querySelector('#my-menu-button');
+menuButton.MaterialExtMenuButton.closeMenu();
+```
+
+### getMenuElement()
+Get the menu element controlled by this button, null if no menu is controlled by this button.
+
+```javascript
+const menuButton = document.querySelector('#my-menu-button');
+const menu = menuButton.MaterialExtMenuButton.getMenuElement(); 
+```
+
+### getSelectedMenuItem()
+Get a selected menu item element, null if no menu item element selected.
+
+```javascript
+const menuButton = document.querySelector('#my-menu-button');
+const element = menuButton.MaterialExtMenuButton.getSelectedMenuItem();
+console.log('Selected menu item', element);
+```
+
+### setSelectedMenuItem(item)
+Set a selected menu item element, typically before menu is opened.
+
+```javascript
+const menuButton = document.querySelector('#my-menu-button');
+const menu = menuButton.MaterialExtMenuButton.getMenuElement(); 
+menuButton.MaterialExtMenuButton.setSelectedMenuItem(menu.children[1]);
+```
+
+Refer to [snippets/menu-button.html](./snippets/menu-button.html) or the [tests](../../test/menu-button/menu-button.spec.js) for detailed usage.
+
+## Configuration options
+
+The MDLEXT CSS classes apply various predefined visual and behavioral enhancements to the menu button. 
+The table below lists the available classes and their effects.
+
+| MDLEXT class                     | Effect | Remarks |
+|----------------------------------|--------|---------|
+|`mdlext-menu-button`              | Basic styling for a menu button | Optional on a div element |
+|`mdlext-js-menu-button`           | Assigns basic MDLEXT behavior to menu button. Identifies the element as a menu button component | Required on the element that should act as a menu button |
+|`mdlext-menu-button__caption`     | Holds the button text | Optional on span element inside menu button element - but required if you want to decorate a button with icons. More than one caption can be used to control various aspects of the button text, e.g. font size. |
+|`material-icons`                  | Defines span as a material icon | Required on an inline element. Decorates button or menu item with an icon |
+|`mdlext-menu`                     | Defines an unordered list container as an MDLEXT component | Required on ul element |
+|`mdlext-menu__item`               | Defines menu options | Required on list item elements |
+|`mdlext-menu__item__caption`      | Holds the menu text | Optional on span element inside list item element - but required if you want to decorate a menu item with icons. More than one caption can be used to control various aspects of the menu text, e.g. font size. |
+|`mdlext-menu__item-separator`     | Items in a menu may be divided into groups by placing an element with a role of `separator` between groups. | Optional; goes on unordered list element |
+|`mdlext-aria-expanded-plus-minus` | State icon. Displays '+' or '-' | Optional; goes on button element |
+|`mdlext-aria-expanded-more-less`  | State icon. Displays 'more' or 'less' Material Design icons | Optional; goes on button element |
+
+> **Note:** 
+> Disabled versions of the menu items are provided, and are invoked with the standard HTML boolean attribute `disabled` 
+`<li class="mdlext-menu__item" disabled>A menu item</li>`. This attribute may be added or removed programmatically via scripting.
+
+> If you decorate the menu button with icons, wrap the button text inside a span to separate icons and text 
+```html
+<button class="mdl-button mdl-button--raised mdl-js-ripple-effect mdl-js-button mdlext-js-menu-button">
+  <i class="material-icons">gesture</i>
+  <span class="mdlext-menu-button__caption">Select</span>
+  <i class="material-icons mdlext-menu-button__aria-expanded-more-less"></i>
+</button>
+```
+
+> If you decorate a menu item with icons, wrap the menu item text inside a span to separate icons and text 
+```html
+<ul id="demo-menu" class="mdlext-menu" hidden>
+  <li class="mdlext-menu__item">
+    <i class="material-icons md-18">help_outline</i>
+    <span class="mdlext-menu__item__caption">Menu item</span>
+    <i class="material-icons">info</i>
+  </li>
+</ul>
+```
diff --git a/node_modules/mdl-ext/src/menu-button/snippets/menu-button.html b/node_modules/mdl-ext/src/menu-button/snippets/menu-button.html
new file mode 100644
index 0000000..784f280
--- /dev/null
+++ b/node_modules/mdl-ext/src/menu-button/snippets/menu-button.html
@@ -0,0 +1,594 @@
+<article>
+<p>A menu button is a button that opens a menu. It is often styled as a typical push button with a
+downward pointing arrow or triangle to hint that activating the button will display a menu.
+The menu button has roles, attributes and behaviour as outlined in
+<a href="https://www.w3.org/TR/wai-aria-practices/#menubutton" target="_blank">WAI-ARIA Authoring Practices</a>.
+</p>
+</article>
+
+<link rel="stylesheet" href="http://code.ionicframework.com/ionicons/2.0.1/css/ionicons.min.css">
+
+<style>
+  .size-22 {
+    font-size: 22px;
+    width: 22px;
+    text-align: center;
+    vertical-align: middle;
+  }
+
+  .mdl-cell p {
+    margin-bottom: 0;
+    white-space: nowrap;
+    text-overflow: ellipsis;
+    overflow: hidden;
+  }
+
+
+  .mdl-textfield.mdlext-js-menu-button .mdl-textfield__input {
+    padding-right: 40px;
+  }
+
+  .mdl-textfield__icon {
+    width: 32px;
+    text-align: left;
+    position: absolute;
+    right: 0;
+    top: 50%;
+    transform: translateY(-50%);
+  }
+
+  .mdl-textfield.is-disabled .mdl-textfield__icon {
+    color: rgba(0, 0, 0, 0.26) !important;
+  }
+
+  .mdl-textfield.is-invalid .mdl-textfield__icon {
+    color: #de3226 !important;
+  }
+
+  #max-width-menu {
+    max-width: 400px;
+  }
+
+</style>
+
+<script>
+  function signedIn(sn) {
+    return 'Signed in with&nbsp;&nbsp;<i class="size-22 icon ion-social-' + sn + '"></i>&nbsp;';
+  }
+  function signedInIcon(sn) {
+    return '<i class="size-22 icon ion-social-' + sn + '"></i>';
+  }
+</script>
+
+<div class="mdl-grid mdl-grid--no-spacing">
+  <div class="mdl-cell mdl-cell--4-col">
+    <p><code>mdl-button</code></p>
+    <button id="btn-social-1" style="width:100%; max-width:300px; height:46px"
+            class="mdl-button mdl-button--colored mdl-button--raised mdl-js-ripple-effect mdl-js-button mdlext-js-menu-button"
+            aria-controls="shared-social-menu" >
+      <i class="material-icons">person_outline</i>
+      <span class="mdlext-menu-button__caption">Sign in with ...</span>
+      <i class="material-icons mdlext-aria-expanded-more-less"></i>
+    </button>
+    <script>
+      document.querySelector('#btn-social-1').addEventListener('menuselect', function(event) {
+        this.querySelector('.mdlext-menu-button__caption').innerHTML = signedIn(event.detail.source.getAttribute('data-value'));
+      });
+    </script>
+  </div> <!--cell -->
+
+  <div class="mdl-cell mdl-cell--4-col">
+    <p><code>mdl-textfield</code></p>
+    <div id="btn-social-2"
+         class="mdl-textfield mdl-js-textfield mdl-textfield--floating-label mdlext-js-menu-button"
+         aria-controls="shared-social-menu">
+      <input class="mdl-textfield__input" type="text" readonly>
+      <label class="mdl-textfield__label">Sign in with ...</label>
+      <i class="material-icons mdl-textfield__icon mdlext-aria-expanded-more-less"></i>
+    </div>
+    <script>
+      document.querySelector('#btn-social-2').addEventListener('menuselect', function(event) {
+        this.MaterialTextfield.change(event.detail.source.querySelector('span').innerHTML);
+      });
+    </script>
+  </div> <!--cell -->
+
+  <div class="mdl-cell mdl-cell--4-col mdlext-bordered-fields">
+    <p><code>mdlext-bordered-fields</code></p>
+    <div id="btn-social-3"
+         class="mdl-textfield mdl-js-textfield mdl-textfield--floating-label mdlext-bordered-fields__icon-right mdlext-js-menu-button"
+         aria-controls="shared-social-menu">
+      <input class="mdl-textfield__input" type="text" readonly>
+      <label class="mdl-textfield__label">Sign in with ...</label>
+      <i class="material-icons mdlext-aria-expanded-more-less"></i>
+    </div>
+    <script>
+      document.querySelector('#btn-social-3').addEventListener('menuselect', function(event) {
+        this.MaterialTextfield.change(event.detail.source.querySelector('span').innerHTML);
+      });
+    </script>
+  </div> <!--cell -->
+
+  <div class="mdl-cell mdl-cell--4-col">
+    <p>custom styled <code>&lt;div&gt;</code></p>
+    <div id="btn-social-4"
+         class="mdlext-menu-button mdlext-js-menu-button" style="width:300px; height:46px; max-width:100%;  border:1px solid green"
+         aria-controls="shared-social-menu">
+      <span class="mdlext-menu-button__caption">Sign in with ...</span>
+      <i class="material-icons mdlext-aria-expanded-more-less"></i>
+    </div>
+    <script>
+      document.querySelector('#btn-social-4').addEventListener('menuselect', function(event) {
+        this.querySelector('span').innerHTML = signedIn(event.detail.source.getAttribute('data-value')) + ', ' +
+          event.detail.source.querySelector('span').innerHTML;
+      });
+    </script>
+  </div> <!--cell -->
+
+
+  <div class="mdl-cell mdl-cell--4-col">
+    <p>mdl-button--icon</p>
+
+    <button id="btn-social-5" style="height:46px; width:46px;"
+            class="mdl-button mdl-js-button mdl-button--icon mdlext-js-menu-button"
+            aria-controls="shared-social-menu">
+      <i class="material-icons">more_vert</i>
+    </button>
+    <script>
+      document.querySelector('#btn-social-5').addEventListener('menuselect', function(event) {
+        this.innerHTML = signedInIcon(event.detail.source.getAttribute('data-value'));
+      });
+    </script>
+
+  </div> <!--cell -->
+
+</div> <!-- grid -->
+
+<ul id="shared-social-menu" class="mdlext-menu" hidden >
+  <li class="mdlext-menu__item" data-value="twitter">
+    <span class="mdlext-menu__item__caption">Twitter</span>
+    <i class="icon ion-social-twitter-outline size-22"></i>
+  </li>
+  <li class="mdlext-menu__item" data-value="github">
+    <span class="mdlext-menu__item__caption">GitHub</span>
+    <i class="ion-social-github-outline size-22"></i>
+  </li>
+  <li class="mdlext-menu__item" data-value="googleplus">
+    <span class="mdlext-menu__item__caption">G+</span>
+    <i class="ion-social-googleplus-outline size-22"></i>
+  </li>
+  <li class="mdlext-menu__item" data-value="linkedin">
+    <span class="mdlext-menu__item__caption">LinkedIn</span>
+    <i class="icon ion-social-linkedin-outline size-22"></i>
+  </li>
+  <li class="mdlext-menu__item" data-value="facebook">
+    <span class="mdlext-menu__item__caption">Facebook</span>
+    <i class="icon ion-social-facebook-outline size-22"></i>
+  </li>
+</ul>
+
+<p style="margin-top: 16px;">Menu buttons positioned left, middle and right, using <code>textalign</code>.</p>
+<div role="presentation">
+  <button class="mdl-button mdl-button--raised mdl-js-ripple-effect mdl-js-button mdlext-js-menu-button">
+    <i class="material-icons">gesture</i>
+    <span class="mdlext-menu-button__caption">Select</span>
+    <i class="material-icons mdlext-aria-expanded-more-less"></i>
+  </button>
+  <ul id="max-width-menu" class="mdlext-menu" hidden >
+    <li class="mdlext-menu__item">
+      <i class="material-icons md-18">info</i>
+      <span class="mdlext-menu__item__caption">Menu item #1</span>
+    </li>
+    <li class="mdlext-menu__item">
+      <i class="material-icons md-18">help_outline</i>
+      <span class="mdlext-menu__item__caption">Menu item #2. A long text to check ellipsis overflow 0123456789</span>
+      <i class="material-icons md-18">radio</i>
+    </li>
+    <li class="mdlext-menu__item-separator"></li>
+    <li class="mdlext-menu__item" disabled>
+      <span class="mdlext-menu__item__caption">Menu item #3, disabled</span>
+      <i class="material-icons md-18">accessibility</i>
+    </li>
+    <li class="mdlext-menu__item-separator"></li>
+    <li class="mdlext-menu__item">
+      <span class="mdlext-menu__item__caption">Menu item #IV</span>
+      <i class="material-icons md-18">build</i>
+    </li>
+    <li class="mdlext-menu__item">
+      <span class="mdlext-menu__item__caption">Menu item #V</span>
+      <i class="material-icons md-18">build</i>
+    </li>
+    <li class="mdlext-menu__item-separator"></li>
+    <li class="mdlext-menu__item">
+      <span class="mdlext-menu__item__caption">Menu item #VI</span>
+      <i class="material-icons md-18">build</i>
+    </li>
+    <li class="mdlext-menu__item">
+      <span class="mdlext-menu__item__caption">Menu item #VII</span>
+      <i class="material-icons md-18">build</i>
+    </li>
+    <li class="mdlext-menu__item">
+      Menu item #n
+    </li>
+  </ul>
+</div>
+
+
+<div role="presentation" style="text-align: center">
+  <button class="mdl-button mdl-button--raised mdl-js-ripple-effect mdl-js-button mdlext-js-menu-button">
+    <i class="material-icons">gesture</i>
+    <span class="mdlext-menu-button__caption">Select</span>
+    <i class="material-icons mdlext-aria-expanded-more-less"></i>
+  </button>
+  <ul class="mdlext-menu" hidden >
+    <li class="mdlext-menu__item">
+      <i class="material-icons md-18">info</i>
+      <span class="mdlext-menu__item__caption">Menu item #1</span>
+    </li>
+    <li class="mdlext-menu__item">
+      <i class="material-icons md-18">help_outline</i>
+      <span class="mdlext-menu__item__caption">Menu item #2</span>
+      <i class="material-icons md-18">radio</i>
+    </li>
+    <li class="mdlext-menu__item" disabled>
+      <span class="mdlext-menu__item__caption">Menu item #3, disabled</span>
+      <i class="material-icons md-18">accessibility</i>
+    </li>
+    <li class="mdlext-menu__item-separator"></li>
+    <li class="mdlext-menu__item">
+      <span class="mdlext-menu__item__caption">Menu item #IV</span>
+      <i class="material-icons md-18">build</i>
+    </li>
+    <li class="mdlext-menu__item">
+      <span class="mdlext-menu__item__caption">Menu item #V</span>
+      <i class="material-icons md-18">build</i>
+    </li>
+    <li class="mdlext-menu__item">
+      <span class="mdlext-menu__item__caption">Menu item #VI</span>
+      <i class="material-icons md-18">build</i>
+    </li>
+    <li class="mdlext-menu__item">
+      <span class="mdlext-menu__item__caption">Menu item #VII</span>
+      <i class="material-icons md-18">build</i>
+    </li>
+    <li class="mdlext-menu__item">
+      <span class="mdlext-menu__item__caption">Menu item #VIII</span>
+      <i class="material-icons md-18">build</i>
+    </li>
+    <li class="mdlext-menu__item">
+      <span class="mdlext-menu__item__caption">Menu item #IX</span>
+      <i class="material-icons md-18">build</i>
+    </li>
+    <li class="mdlext-menu__item">
+      <span class="mdlext-menu__item__caption">Menu item #X</span>
+      <i class="material-icons md-18">build</i>
+    </li>
+    <li class="mdlext-menu__item">
+      <span class="mdlext-menu__item__caption">Menu item #XI</span>
+      <i class="material-icons md-18">build</i>
+    </li>
+    <li class="mdlext-menu__item">
+      <span class="mdlext-menu__item__caption">Menu item #XII</span>
+      <i class="material-icons md-18">build</i>
+    </li>
+    <li class="mdlext-menu__item">
+      <span class="mdlext-menu__item__caption">Menu item #XIII</span>
+      <i class="material-icons md-18">build</i>
+    </li>
+    <li class="mdlext-menu__item">
+      <span class="mdlext-menu__item__caption">Menu item #XIV</span>
+      <i class="material-icons md-18">build</i>
+    </li>
+    <li class="mdlext-menu__item">
+      <span class="mdlext-menu__item__caption">Menu item #XV</span>
+      <i class="material-icons md-18">build</i>
+    </li>
+    <li class="mdlext-menu__item">
+      <span class="mdlext-menu__item__caption">Menu item #XVI</span>
+      <i class="material-icons md-18">build</i>
+    </li>
+    <li class="mdlext-menu__item">
+      <span class="mdlext-menu__item__caption">Menu item #XVII</span>
+      <i class="material-icons md-18">build</i>
+    </li>
+    <li class="mdlext-menu__item">
+      <span class="mdlext-menu__item__caption">Menu item #XVIII</span>
+      <i class="material-icons md-18">build</i>
+    </li>
+    <li class="mdlext-menu__item">
+      <span class="mdlext-menu__item__caption">Menu item #XIX</span>
+      <i class="material-icons md-18">build</i>
+    </li>
+    <li class="mdlext-menu__item">
+      <span class="mdlext-menu__item__caption">Menu item #XX</span>
+      <i class="material-icons md-18">build</i>
+    </li>
+    <li class="mdlext-menu__item">
+      Menu item #n
+    </li>
+  </ul>
+</div>
+
+
+<div role="presentation" style="text-align: right">
+  <button class="mdl-button mdl-button--raised mdl-js-ripple-effect mdl-js-button mdlext-js-menu-button">
+    <i class="material-icons">gesture</i>
+    <span class="mdlext-menu-button__caption">Select</span>
+    <i class="material-icons mdlext-aria-expanded-more-less"></i>
+  </button>
+  <ul class="mdlext-menu" hidden >
+    <li class="mdlext-menu__item">
+      <i class="material-icons md-18">info</i>
+      <span class="mdlext-menu__item__caption">Menu item #1</span>
+    </li>
+    <li class="mdlext-menu__item">
+      <i class="material-icons md-18">help_outline</i>
+      <span class="mdlext-menu__item__caption">Menu item #2</span>
+      <i class="material-icons md-18">radio</i>
+    </li>
+    <li class="mdlext-menu__item" disabled>
+      <span class="mdlext-menu__item__caption">Menu item #3, disabled</span>
+      <i class="material-icons md-18">accessibility</i>
+    </li>
+    <li class="mdlext-menu__item">
+      <span class="mdlext-menu__item__caption">Menu item #IV</span>
+      <i class="material-icons md-18">build</i>
+    </li>
+    <li class="mdlext-menu__item-separator"></li>
+    <li class="mdlext-menu__item">
+      <span class="mdlext-menu__item__caption">Menu item #V</span>
+      <i class="material-icons md-18">build</i>
+    </li>
+    <li class="mdlext-menu__item">
+      <span class="mdlext-menu__item__caption">Menu item #VI</span>
+      <i class="material-icons md-18">build</i>
+    </li>
+    <li class="mdlext-menu__item">
+      <span class="mdlext-menu__item__caption">Menu item #VII</span>
+      <i class="material-icons md-18">build</i>
+    </li>
+    <li class="mdlext-menu__item">
+      Menu item #n
+    </li>
+  </ul>
+</div>
+
+
+<p style="margin-top: 16px">This menu button has WAIA roles and attributes coded in markup</p>
+<button id="aria-demo-button"
+        class="mdl-button mdl-button--raised mdl-button--accent mdl-js-ripple-effect mdl-js-button mdlext-js-menu-button"
+        role="button"
+        aria-haspopup="true"
+        aria-controls="menu-example-dropdown"
+        aria-expanded="false"
+        tabindex="0">
+  <span class="mdlext-menu-button__caption">Select a size</span>
+  <i class="mdlext-aria-expanded-plus-minus"></i>
+</button>
+<script>
+  document.querySelector('#aria-demo-button').addEventListener('menuselect', function(event) {
+    this.querySelector('span').innerHTML = 'Size: ' + event.detail.source.innerHTML;
+  });
+</script>
+<ul id="menu-example-dropdown"
+    class="mdlext-menu"
+    role="menu"
+    hidden >
+  <li class="mdlext-menu__item" role="menuitem">X Small</li>
+  <li class="mdlext-menu__item-separator" role="separator"></li>
+  <li class="mdlext-menu__item" role="menuitem">Small</li>
+  <li class="mdlext-menu__item" role="menuitem">Medium</li>
+  <li class="mdlext-menu__item" role="menuitem">Large</li>
+  <li class="mdlext-menu__item-separator" role="separator"></li>
+  <li class="mdlext-menu__item" role="menuitem">X Large</li>
+  <li class="mdlext-menu__item" role="menuitem">XXX Large</li>
+</ul>
+
+<p style="margin-top: 16px">A disabled menu button should do nothing</p>
+<div role="presentation">
+  <button class="mdl-button mdl-js-button mdl-button--raised mdl-js-ripple-effect mdlext-js-menu-button" disabled>
+    <span class="mdlext-menu-button__caption">Disabled</span>
+    <i class="material-icons mdlext-aria-expanded-more-less"></i>
+  </button>
+  <ul class="mdlext-menu" hidden>
+    <li class="mdlext-menu__item">Menu item #1</li>
+  </ul>
+</div>
+
+
+<p style="margin-top: 16px">Menu buttons inside a table. Menus placed inside and after the table element to verify
+  that positioning works as expected.</p>
+
+<div style="position:relative; border:2px solid green; overflow: hidden;">
+<p>The box with green borders has <code>overflow:hidden</code></p>
+<div>
+
+  <table id="a-table-with-menu-buttons"
+         class="mdl-data-table mdl-js-data-table mdl-data-table--selectable mdl-shadow--2dp" style="width: 48%; float:left;">
+  <thead>
+  <tr>
+    <th class="mdl-data-table__cell--non-numeric">Material</th>
+    <th>Quantity</th>
+    <th>Unit price</th>
+  </tr>
+  </thead>
+  <tbody>
+  <tr>
+    <td class="mdl-data-table__cell--non-numeric">Acrylic (Transparent)</td>
+    <td>
+      <span style="width:40px; display: inline-block;"></span>
+      <button class="mdl-button mdl-js-button mdl-button--icon mdl-button--primary mdlext-js-menu-button"
+              aria-controls="table-menu-example">
+        <i class="mdlext-aria-expanded-more-less"></i>
+      </button>
+    </td>
+    <td>$2.90</td>
+  </tr>
+  <tr>
+    <td class="mdl-data-table__cell--non-numeric">Plywood (Birch)</td>
+    <td>
+      <span style="width:40px; display: inline-block;"></span>
+      <button class="mdl-button mdl-js-button mdl-button--icon mdl-button--primary mdlext-js-menu-button"
+              aria-controls="table-menu-example">
+        <i class="mdlext-aria-expanded-more-less"></i>
+      </button>
+    </td>
+    <td>$1.25</td>
+  </tr>
+  <tr>
+    <td class="mdl-data-table__cell--non-numeric">Laminate (Gold on Blue)</td>
+    <td>
+      <span style="width:40px; display: inline-block;"></span>
+      <button class="mdl-button mdl-button--icon mdl-button--primary mdl-js-button mdlext-js-menu-button"
+              aria-controls="table-menu-example">
+        <i class="mdlext-aria-expanded-more-less"></i>
+      </button>
+    </td>
+    <td>$2.35</td>
+  </tr>
+  </tbody>
+  </table>
+
+  <script>
+    document.querySelector('#a-table-with-menu-buttons').addEventListener('menuselect', function(event) {
+      var span = event.target.closest('td').querySelector('span');
+      span.innerHTML = event.detail.source.getAttribute('data-value');
+    });
+  </script>
+
+  <div role="presentation" style="width:48%; float:right;">
+    <p style="margin-top: 16px">This menu button has a menu with dark color theme, <code>mdlext-dark-color-theme</code> class</p>
+
+    <button class="mdl-button mdl-button--raised mdl-js-ripple-effect mdl-js-button mdlext-js-menu-button">
+      <i class="material-icons">gesture</i>
+      <span class="mdlext-menu-button__caption">Select</span>
+      <i class="material-icons mdlext-aria-expanded-more-less"></i>
+    </button>
+    <ul class="mdlext-menu mdlext-dark-color-theme" hidden >
+      <li class="mdlext-menu__item">
+        <i class="material-icons md-18">info</i>
+        <span class="mdlext-menu__item__caption">Menu item #1</span>
+      </li>
+      <li class="mdlext-menu__item">
+        <i class="material-icons md-18">help_outline</i>
+        <span class="mdlext-menu__item__caption">Menu item #2. A long text to check ellipsis overflow 0123456789</span>
+        <i class="material-icons md-18">radio</i>
+      </li>
+      <li class="mdlext-menu__item-separator"></li>
+      <li class="mdlext-menu__item" disabled>
+        <span class="mdlext-menu__item__caption">Menu item #3, disabled</span>
+        <i class="material-icons md-18">accessibility</i>
+      </li>
+      <li class="mdlext-menu__item-separator"></li>
+      <li class="mdlext-menu__item">
+        <span class="mdlext-menu__item__caption">Menu item #IV</span>
+        <i class="material-icons md-18">build</i>
+      </li>
+      <li class="mdlext-menu__item">
+        <span class="mdlext-menu__item__caption">Menu item #V</span>
+        <i class="material-icons md-18">build</i>
+      </li>
+      <li class="mdlext-menu__item-separator"></li>
+      <li class="mdlext-menu__item">
+        <span class="mdlext-menu__item__caption">Menu item #VI</span>
+        <i class="material-icons md-18">build</i>
+      </li>
+    </ul>
+  </div>
+
+</div>
+</div>
+
+<ul id="table-menu-example" class="mdlext-menu" hidden >
+  <li class="mdlext-menu__item" data-value="10">Ten</li>
+  <li class="mdlext-menu__item" data-value="25">Twentyfive</li>
+  <li class="mdlext-menu__item" data-value="50">Fifty</li>
+</ul>
+
+
+<style>
+  .demo-grid {
+    margin-top: 32px;
+  }
+  .demo-grid .mdl-cell {
+    background: rgb(63,81,181);
+    text-align: center;
+    color: white;
+    padding: 16px 8px;
+    border: 1px solid #aaaaaa;
+  }
+  .demo-grid .mdl-cell:nth-child(odd) {
+    background: rgb(33,150,243);
+  }
+</style>
+
+
+<div id="a-grid-with-menu-buttons" class="demo-grid">
+  <p>Menu buttons inside <code>mdl-grid</code></p>
+
+  <div id="menu-button-grid" class="mdl-grid mdl-grid--no-spacing">
+    <div class="mdl-cell mdl-cell--4-col mdl-cell--4-col-tablet mdl-cell--2-col-phone">
+      <button class="mdl-button mdl-button--raised mdl-button--accent mdl-js-ripple-effect mdl-js-button mdlext-js-menu-button">
+        <span class="mdlext-menu-button__caption">Select a size</span>
+        <i class="mdlext-aria-expanded-plus-minus"></i>
+      </button>
+      <ul class="mdlext-menu"
+          role="menu"
+          hidden >
+        <li class="mdlext-menu__item" role="menuitem">Small</li>
+        <li class="mdlext-menu__item" role="menuitem">Medium</li>
+        <li class="mdlext-menu__item" role="menuitem">Large</li>
+      </ul>
+    </div>
+    <div class="mdl-cell mdl-cell--5-col mdl-cell--4-col-tablet mdl-cell--2-col-phone">
+      <button class="mdl-button mdl-button--raised mdl-button--accent mdl-js-ripple-effect mdl-js-button mdlext-js-menu-button">
+        <span class="mdlext-menu-button__caption">Select a size</span>
+        <i class="mdlext-aria-expanded-plus-minus"></i>
+      </button>
+      <ul class="mdlext-menu"
+          role="menu"
+          hidden >
+        <li class="mdlext-menu__item" role="menuitem">Small</li>
+        <li class="mdlext-menu__item" role="menuitem">Medium</li>
+        <li class="mdlext-menu__item" role="menuitem">Large</li>
+      </ul>
+    </div>
+    <div class="mdl-cell mdl-cell--3-col mdl-cell--4-col-tablet mdl-cell--hide-phone">
+      <button class="mdl-button mdl-button--raised mdl-button--accent mdl-js-ripple-effect mdl-js-button mdlext-js-menu-button">
+        <span class="mdlext-menu-button__caption">Select a size</span>
+        <i class="mdlext-aria-expanded-plus-minus"></i>
+      </button>
+      <ul class="mdlext-menu"
+          role="menu"
+          hidden >
+        <li class="mdlext-menu__item" role="menuitem">Small</li>
+        <li class="mdlext-menu__item" role="menuitem">Medium</li>
+        <li class="mdlext-menu__item" role="menuitem">Large</li>
+      </ul>
+    </div>
+  </div>
+</div>
+<script>
+  document.querySelector('#a-grid-with-menu-buttons').addEventListener('menuselect', function(event) {
+    event.target.querySelector('span').innerHTML = 'Size: ' + event.detail.source.innerHTML;
+  });
+</script>
+
+<div style="margin-bottom:256px;"></div>
+
+<!--
+https://www.w3.org/TR/wai-aria-practices/#menubutton
+http://w3c.github.io/aria-practices/examples/menu-button/menu-button-1.html
+http://w3c.github.io/aria-practices/examples/menu-button/menu-button-2.html
+http://tympanus.net/codrops/2012/10/04/custom-drop-down-list-styling/
+http://www.slideshare.net/webaxe/html5-dev-con-2012-aria-widget
+http://terrillthompson.com/blog/474
+https://github.com/davidtheclark/react-aria-menubutton
+https://codepen.io/tiffanytse/pen/Dkvtr
+https://codepen.io/andytran/pen/vLNGvN
+https://codepen.io/dapacreative/pen/WQoLzb
+https://codepen.io/gabrieltomescu/pen/ZGGyPK
+https://codepen.io/Idered/pen/vowrB
+https://codepen.io/Stedesign/pen/DbAJh
+http://markbirbeck.com/2015/10/14/a-mixin-approach-to-material-design-lite-using-sass/
+-->