Security News
RubyGems.org Adds New Maintainer Role
RubyGems.org has added a new "maintainer" role that allows for publishing new versions of gems. This new permission type is aimed at improving security for gem owners and the service overall.
@material/menu
Advanced tools
@material/menu is a Material Design menu component for the web. It provides a simple way to create menus that follow the Material Design guidelines, including support for nested menus, keyboard navigation, and accessibility features.
Basic Menu
This code demonstrates how to create a basic menu using the @material/menu package. It initializes a menu component and opens it.
import {MDCMenu} from '@material/menu';
const menu = new MDCMenu(document.querySelector('.mdc-menu'));
menu.open = true;
Menu with Items
This code shows how to create a menu with items and add an event listener to handle item clicks.
import {MDCMenu} from '@material/menu';
const menu = new MDCMenu(document.querySelector('.mdc-menu'));
menu.open = true;
const listItem = document.querySelector('.mdc-list-item');
listItem.addEventListener('click', () => {
console.log('Item clicked');
});
Nested Menus
This code demonstrates how to create nested menus using the @material/menu package. It initializes a parent menu and a child menu, and opens the child menu when an item in the parent menu is clicked.
import {MDCMenu} from '@material/menu';
const parentMenu = new MDCMenu(document.querySelector('.mdc-menu-parent'));
const childMenu = new MDCMenu(document.querySelector('.mdc-menu-child'));
parentMenu.open = true;
const parentItem = document.querySelector('.mdc-list-item-parent');
parentItem.addEventListener('click', () => {
childMenu.open = true;
});
react-select is a flexible and customizable menu component for React applications. It provides a wide range of features including multi-select, async options, and customizable styles. Compared to @material/menu, react-select is more focused on providing a rich set of features for select inputs rather than general-purpose menus.
rc-menu is a React component for creating menus. It supports nested menus, keyboard navigation, and customizable styles. While it offers similar functionality to @material/menu, rc-menu is specifically designed for React applications and provides more flexibility in terms of customization.
semantic-ui-react is the official React integration for Semantic UI. It includes a Menu component that provides a wide range of features including vertical and horizontal menus, submenus, and item grouping. Compared to @material/menu, semantic-ui-react offers a more comprehensive set of UI components and is designed to work seamlessly with the Semantic UI framework.
The MDC Menu component is a spec-aligned menu component adhering to the Material Design menu specification. It implements simple menus. Menus require JavaScript to work correctly, but the open and closed states are correct on first render.
npm install --save @material/menu
A simple menu is usually closed, appearing when opened. It is appropriate for any display size.
<div class="mdc-simple-menu" tabindex="-1">
<ul class="mdc-simple-menu__items mdc-list" role="menu" aria-hidden="true">
<li class="mdc-list-item" role="menuitem" tabindex="0">
A Menu Item
</li>
<li class="mdc-list-item" role="menuitem" tabindex="0">
Another Menu Item
</li>
</ul>
</div>
Note: adding a
tabindex
of0
to the menu items places them in the tab order. Adding atabindex
of-1
to the root element makes it programmatically focusable, without placing it in the tab order. This allows the menu to be focused on open, so that the next Tab keypress moves to the first menu item. If you would like the first menu item to be automatically focused instead, removetabindex="-1"
from the root element.
let menu = new mdc.menu.MDCSimpleMenu(document.querySelector('.mdc-simple-menu'));
// Add event listener to some button to toggle the menu on and off.
document.querySelector('.some-button').addEventListener('click', () => menu.open = !menu.open);
You can start the menu in its open state by adding the mdc-simple-menu--open
class to your HTML:
<div class="mdc-simple-menu mdc-simple-menu--open">
...
</div>
The menu can either be positioned manually, or automatically, by anchoring it to an element.
The menu understands the concept of an anchor, which it can use to determine how to position itself, and which corner to open from.
The anchor can either be a visible element that the menu is a child of:
<div class="toolbar mdc-menu-anchor">
<div class="mdc-simple-menu">
...
</div>
</div>
or a wrapper element that contains the actual visible element to attach to:
<div class="mdc-menu-anchor">
<button>Open Menu</button>
<div class="mdc-simple-menu">
...
</div>
</div>
Note:
overflow: visible
andposition: relative
will be set on the element withmdc-menu-anchor
to ensure that the menu is positioned and displayed correctly.
The menu will check if its parent element has the mdc-menu-anchor
class set, and if so, it will automatically position
itself relative to this anchor element. It will open from the top left (top right in RTL) corner of the anchor by
default, but will choose an appropriate different corner if close to the edge of the screen.
The menu is position: absolute
by default, and must be positioned by the user when doing manual positioning.
<div class="container">
<div class="mdc-simple-menu" style="top:0; left: 0;">
...
</div>
</div>
The menu will open from the top left by default (top right in RTL). Depending on how you've positioned your button, you
may want to change the point it opens from.
To override the opening point, you can style transform-origin
directly, or use one of the following convenience
classes:
class name | description |
---|---|
mdc-simple-menu--open-from-top-left | Open the menu from the top left. |
mdc-simple-menu--open-from-top-right | Open the menu from the top right. |
mdc-simple-menu--open-from-bottom-left | Open the menu from the bottom left. |
mdc-simple-menu--open-from-bottom-right | Open the menu from the bottom right. |
When used in components such as MDC Menu, mdc-list-item
's can be disabled.
To disable a list item, set aria-disabled
to "true"
, and set tabindex
to "-1"
.
<div class="mdc-simple-menu" tabindex="-1">
<ul class="mdc-simple-menu__items mdc-list" role="menu" aria-hidden="true">
<li class="mdc-list-item" role="menuitem" tabindex="0">
A Menu Item
</li>
<li class="mdc-list-item" role="menuitem" tabindex="-1" aria-disabled="true">
Disabled Menu Item
</li>
</ul>
</div>
MDC Simple Menu ships with a Component / Foundation combo which allows for frameworks to richly integrate the correct menu behaviors into idiomatic components.
The component has a read-write property, open
, which keeps track of the visual state of the component.
// Analyse current state.
console.log('The menu is ' + (menu.open ? 'open' : 'closed'));
// Open menu.
menu.open = true;
// Close menu.
menu.open = false;
It also has two lower level methods, which control the menu directly, by showing (opening) and hiding (closing) it:
// Show (open) menu.
menu.show();
// Hide (close) menu.
menu.hide();
// Show (open) menu, and focus the menu item at index 1.
menu.show({focusIndex: 1});
You can still use the open
getter property even if showing and hiding directly:
menu.show();
console.log(`Menu is ${menu.open ? 'open' : 'closed'}.`);
import {MDCSimpleMenu, MDCSimpleMenuFoundation, util} from '@material/menu';
const mdcMenu = require('mdc-menu');
const MDCSimpleMenu = mdcMenu.MDCSimpleMenu;
const MDCSimpleMenuFoundation = mdcMenu.MDCSimpleMenuFoundation;
const util = mdcMenu.util;
require(['path/to/mdc-menu'], mdcMenu => {
const MDCSimpleMenu = mdcMenu.MDCSimpleMenu;
const MDCSimpleMenuFoundation = mdcMenu.MDCSimpleMenuFoundation;
const util = mdcMenu.util;
});
const MDCSimpleMenu = mdc.Menu.MDCSimpleMenu;
const MDCSimpleMenuFoundation = mdc.Menu.MDCSimpleMenuFoundation;
const util = mdc.menu.util;
If you do not care about retaining the component instance for the simple menu, simply call attachTo()
and pass it a
DOM element.
mdc.MDCSimpleMenu.attachTo(document.querySelector('.mdc-simple-menu'));
Simple menus can easily be initialized using their default constructors as well, similar to attachTo
.
import {MDCSimpleMenu} from '@material/menu';
const menu = new MDCSimpleMenu(document.querySelector('.mdc-simple-menu'));
When a menu item is selected, the menu component will emit a MDCSimpleMenu:selected
custom event
with the following detail
data:
property name | type | description |
---|---|---|
item | HTMLElement | The DOM element for the selected item |
index | number | The index of the selected item |
If the menu is closed with no selection made (for example, if the user hits Escape
while it's open), a MDCSimpleMenu:cancel
custom event is emitted instead, with no data attached.
MDC Simple Menu ships with an MDCSimpleMenuFoundation
class that external frameworks and libraries can use to
integrate the component. As with all foundation classes, an adapter object must be provided.
The adapter for simple menu must provide the following functions, with correct signatures:
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 boolean indicating whether element has a given class. |
hasNecessaryDom() => boolean | Returns boolean indicating whether the necessary DOM is present (namely, the mdc-simple-menu__items container). |
getAttributeForEventTarget(target: EventTarget, attributeName: string) => string | Returns the value of a given attribute on an event target. |
eventTargetHasClass: (target: EventTarget, className: string) => boolean | Returns true if the event target has a given class. |
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. |
setScale(x: string, y: string) => void | Sets the transform on the root element to the provided (x, y) scale. |
setInnerScale(x: string, y: string) => void | Sets the transform on the items container to the provided (x, y) scale. |
getNumberOfItems() => numbers | 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'. |
getYParamsForItemAtIndex(index: number) => {top: number, height: number} | Returns an object with the offset top and offset height values for the item element inside the items container at the provided index. Note that this is an index into the list of item elements, and not necessarily every child element of the list. |
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. The same notice for index applies here as above. |
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. The same notice for index applies here as above. |
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 the 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 simple menu is focused. |
focus() => void | Focuses the root element of the simple 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. |
getAccurateTime() => number | Returns a number representing the number of milliseconds (and fractional milliseconds, as the decimal part) since a given point in time, which should remain constant during the component's lifecycle. Ideally, this should be provided by window.performance.now() , which has enough precision for high frequency animation calculations. Using Date.now() or equivalent may result in some aliasing in animations. |
Opens the menu. Takes an options object containing a focusIndex
property that specifies the index of the menu item to be focused. If the options object or focusIndex
is omitted, no menu item will be focused.
Closes the menu.
Returns whether or not the menu is open.
External frameworks and libraries can use the following utility methods when integrating a component.
Returns the name of the correct transform property to use on the current browser.
Clamps a value between the minimum and the maximum, returning the clamped value.
Returns the easing value to apply at time t, for a given cubic bezier curve.
Control points P0 and P3 are assumed to be (0,0) and (1,1), respectively.
Parameters are as follows:
- time: The current time in the animation, scaled between 0 and 1.
- x1: The x value of control point P1.
- y1: The y value of control point P1.
- x2: The x value of control point P2.
- y2: The y value of control point P2.
FAQs
The Material Components for the web menu component
The npm package @material/menu receives a total of 163,029 weekly downloads. As such, @material/menu popularity was classified as popular.
We found that @material/menu demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 15 open source maintainers collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security News
RubyGems.org has added a new "maintainer" role that allows for publishing new versions of gems. This new permission type is aimed at improving security for gem owners and the service overall.
Security News
Node.js will be enforcing stricter semver-major PR policies a month before major releases to enhance stability and ensure reliable release candidates.
Security News
Research
Socket's threat research team has detected five malicious npm packages targeting Roblox developers, deploying malware to steal credentials and personal data.