solids
Version:
CSS-only Material Design Primitives
204 lines (165 loc) • 10.1 kB
Markdown
<!--docs:
title: "Menus"
layout: detail
section: components
excerpt: "Non-cascading Material Design menus."
iconId: menu
path: /catalog/menus/
-->
# Menus
<!--<div class="article__asset">
<a class="article__asset-link"
href="https://material-components-web.appspot.com/menu.html">
<img src="{{ site.rootpath }}/images/mdc_web_screenshots/menus.png" width="178" alt="Menus screenshot">
</a>
</div>-->
The MDC Menu component is a spec-aligned menu component adhering to the
[Material Design menu specification](https://material.io/go/design-menus).
Menus require JavaScript to properly position themselves when opening.
## Design & API Documentation
<ul class="icon-list">
<li class="icon-list-item icon-list-item--spec">
<a href="https://material.io/go/design-menus">Material Design guidelines: Menus</a>
</li>
<li class="icon-list-item icon-list-item--link">
<a href="https://material-components-web.appspot.com/menu.html">Demo</a>
</li>
</ul>
## Installation
```
npm install /menu
```
## Usage
### HTML Structure
A menu is initially hidden, appearing when opened via the JS API. It is appropriate for any display size.
```html
<div class="mdc-menu" tabindex="-1">
<ul class="mdc-menu__items solid_list" role="menu" aria-hidden="true">
<li class="list_item" role="menuitem" tabindex="0">
A Menu Item
</li>
<li class="list_item" role="menuitem" tabindex="0">
Another Menu Item
</li>
</ul>
</div>
```
#### Anchor To Parent
The menu can be positioned to automatically anchor to a parent element when opened.
```html
<div id="toolbar" class="toolbar mdc-menu-anchor">
<div class="mdc-menu">
...
</div>
</div>
```
#### Anchor To Element Within Wrapper
The menu can be positioned to automatically anchor to another element, by wrapping the other element with the anchor class.
```html
<div id="demo-menu" class="mdc-menu-anchor">
<button id="menu-button">Open Menu</button>
<div class="mdc-menu">
...
</div>
</div>
```
#### Disabled menu items
When used in components such as MDC Menu, list items can be disabled.
To disable a list item, set `aria-disabled` property to `"true"`, and set `tabindex` to `"-1"`.
```html
<div class="mdc-menu" tabindex="-1">
<ul class="mdc-menu__items solid_list" role="menu" aria-hidden="true">
<li class="list_item" role="menuitem" tabindex="0">
A Menu Item
</li>
<li class="list_item" role="menuitem" tabindex="-1" aria-disabled="true">
Disabled Menu Item
</li>
</ul>
</div>
```
### CSS Classes
CSS Class | Description
--- | ---
`mdc-menu` | Mandatory
`mdc-menu--animating-open` | Indicates the menu is currently animating open. This class is removed once the animation completes.
`mdc-menu--open` | Indicates the menu is currently open, or is currently animating open.
`mdc-menu--animating-closed` | Indicates the menu is currently animating closed. This class is removed once the animation completes.
### JS Examples
```js
// Instantiation
var menuEl = document.querySelector('#toolbar');
var menu = new mdc.menu.MDCMenu(menuEl);
var menuButtonEl = document.querySelector('#menu-button');
// Toggle menu open
menuButtonEl.addEventListener('click', function() {
menu.open = !menu.open;
});
// Listen for selected item
menuEl.addEventListener('MDCMenu:selected', function(evt) {
var detail = evt.detail;
});
// Set Anchor Corner to Bottom End
menu.setAnchorCorner(Corner.BOTTOM_END);
// Turn off menu open animations
menu.quickOpen = true;
```
### `MDCMenu`
See [Importing the JS component](../../docs/importing-js.md) for more information on how to import JavaScript.
Property | Value Type | Description
--- | --- | ---
`open` | Boolean | Proxies to the foundation's `isOpen`/(`open`, `close`) methods.
`items` | Array<Element> | Proxies to the foundation's container to query for all `.list_item[role]` elements.
`itemsContainer` | Element | Queries the foundation's root element for the `mdc-menu__items` container element.
`quickOpen` | Boolean | Proxies to the foundation's `setQuickOpen()` method.
Method Signature | Description
--- | ---
`show({focusIndex: ?number}) => void` | Proxies to the foundation's `open()` method. An optional config parameter allows the caller to specify which item should receive focus after the menu opens.
`hide() => void` | Proxies to the foundation's `close()` method.
`setAnchorCorner(Corner) => void` | Proxies to the foundation's `setAnchorCorner(Corner)` method.
`setAnchorMargin(AnchorMargin) => void` | Proxies to the foundation's `setAnchorMargin(AnchorMargin)` method.
`getDefaultFoundation() => MDCMenuFoundation` | Returns the foundation.
### `MDCMenuAdapter`
Method Signature | Description
--- | ---
`addClass(className: string) => void` | Adds a class to the root element.
`removeClass(className: string) => void` | Removes a class from the root element.
`hasClass(className: string) => boolean` | Returns a boolean indicating whether the root element has a given class.
`hasNecessaryDom() => boolean` | Returns boolean indicating whether the necessary DOM is present (namely, the `mdc-menu__items` container).
`getAttributeForEventTarget(target: EventTarget, attributeName: string) => string` | Returns the value of a given attribute on an event target.
`getInnerDimensions() => {width: number, height: number}` | Returns an object with the items container width and height.
`hasAnchor: () => boolean` | Returns whether the menu has an anchor for positioning.
`getAnchorDimensions() => {width: number, height: number, top: number, right: number, bottom: number, left: number}` | Returns an object with the dimensions and position of the anchor (same semantics as `DOMRect`).
`getWindowDimensions() => {width: number, height: number}` | Returns an object with width and height of the page, in pixels.
`getNumberOfItems() => number` | Returns the number of _item_ elements inside the items container. In our vanilla component, we determine this by counting the number of list items whose `role` attribute corresponds to the correct child role of the role present on the menu list element. For example, if the list element has a role of `menu` this queries for all elements that have a role of `menuitem`.
`registerInteractionHandler(type: string, handler: EventListener) => void` | Adds an event listener `handler` for event type `type`.
`deregisterInteractionHandler(type: string, handler: EventListener) => void` | Removes an event listener `handler` for event type `type`.
`registerBodyClickHandler(handler: EventListener) => void` | Adds an event listener `handler` for event type `click`.
`deregisterBodyClickHandler(handler: EventListener) => void` | Removes an event listener `handler` for event type `click`.
`getIndexForEventTarget(target: EventTarget) => number` | Checks to see if the `target` of an event pertains to one of the menu items, and if so returns the index of that item. Returns -1 if the target is not one of the menu items.
`notifySelected(evtData: {index: number}) => void` | Dispatches an event notifying listeners that a menu item has been selected. The function should accept an `evtData` parameter containing an object with an `index` property representing the index of the selected item. Implementations may choose to supplement this data with additional data, such as the item itself.
`notifyCancel() => void` | Dispatches an event notifying listeners that the menu has been closed with no selection made.
`saveFocus() => void` | Stores the currently focused element on the document, for restoring with `restoreFocus`.
`restoreFocus() => void` | Restores the previously saved focus state, by making the previously focused element the active focus again.
`isFocused() => boolean` | Returns a boolean value indicating whether the root element of the menu is focused.
`focus() => void` | Focuses the root element of the menu.
`getFocusedItemIndex() => number` | Returns the index of the currently focused menu item (-1 if none).
`focusItemAtIndex(index: number) => void` | Focuses the menu item with the provided index.
`isRtl() => boolean` | Returns boolean indicating whether the current environment is RTL.
`setTransformOrigin(value: string) => void` | Sets the transform origin for the menu element.
`setPosition(position: {top: string, right: string, bottom: string, left: string}) => void` | Sets the position of the menu element.
`setMaxHeight(value: string) => void` | Sets `max-height` style for the menu element.
### `MDCMenuFoundation`
Method Signature | Description
--- | ---
`setAnchorCorner(corder: Corner) => void` | Sets the corner that the menu will be anchored to. See [constants.js](https://github.com/material-components/material-components-web/blob/cc299230728ba5a994866ebd31aaaf1a0f4cc87f/packages/mdc-menu/constants.js#L73)
`setAnchorMargin(margin: AnchorMargin) => void` | Sets the distance from the anchor point that the menu should be shown.
`open({focusIndex: ?number}) => void` | Opens the menu. Optionally accepts an object with a `focusIndex` parameter to indicate which list item should receive focus when the menu is opened.
`close(evt: ?Event)` | Closes the menu. Optionally accepts the event to check if the target is disabled before closing the menu.
`isOpen() => boolean` | Returns a boolean indicating whether the menu is open.
`setQuickOpen(quickOpen: boolean) => void` | Sets whether the menu should open and close without animation when the `open`/`close` methods are called.
### Events
Event Name | Data | Description
--- | --- | ---
`MDCMenu:selected` | `{detail: {item: HTMLElement, index: number}}` | Used to indicate when an element has been selected. This event also includes the item selected and the list index of that item.
`MDCMenu:cancel` | none | Event emitted when the menu is closed with no selection made (e.g. if the user hits `Esc` while it's open, or clicks somewhere else on the page).