What is @material/menu-surface?
@material/menu-surface is a package from Material Design Components (MDC) that provides a foundation for creating menu surfaces. These are surfaces that can be used to display a list of choices, such as a dropdown menu or a context menu.
What are @material/menu-surface's main functionalities?
Basic Menu Surface
This code demonstrates how to create a basic menu surface and open it using the MDCMenuSurface class.
import {MDCMenuSurface} from '@material/menu-surface';
const menuSurfaceElement = document.querySelector('.mdc-menu-surface');
const menuSurface = new MDCMenuSurface(menuSurfaceElement);
menuSurface.open();
Anchor Menu Surface
This code shows how to anchor a menu surface to a specific element, making it appear relative to that element.
import {MDCMenuSurface} from '@material/menu-surface';
const menuSurfaceElement = document.querySelector('.mdc-menu-surface');
const menuSurface = new MDCMenuSurface(menuSurfaceElement);
const anchorElement = document.querySelector('.mdc-menu-surface--anchor');
menuSurface.setAnchorElement(anchorElement);
menuSurface.open();
Menu Surface with Event Listeners
This code demonstrates how to add event listeners to a menu surface to handle open and close events.
import {MDCMenuSurface} from '@material/menu-surface';
const menuSurfaceElement = document.querySelector('.mdc-menu-surface');
const menuSurface = new MDCMenuSurface(menuSurfaceElement);
menuSurface.listen('MDCMenuSurface:opened', () => {
console.log('Menu surface opened');
});
menuSurface.listen('MDCMenuSurface:closed', () => {
console.log('Menu surface closed');
});
menuSurface.open();
Other packages similar to @material/menu-surface
react-select
react-select is a flexible and beautiful Select Input control for ReactJS with multiselect, autocomplete, async and creatable support. It provides a more comprehensive solution for dropdowns and select inputs compared to @material/menu-surface, which is more focused on the menu surface itself.
rc-menu
rc-menu is a React component for creating menus. It offers a wide range of customization options and is highly flexible, making it a good alternative to @material/menu-surface for React applications.
semantic-ui-react
semantic-ui-react is the official React integration for Semantic UI. It includes a variety of UI components, including menus, which are more feature-rich and integrated with the overall Semantic UI framework compared to @material/menu-surface.
The MDC Menu Surface component is a reusable surface that appears above the content of the
page and can be positioned adjacent to an element. Menu Surfaces require JavaScript to properly position
themselves when opening.
Design & API Documentation
Installation
npm install @material/menu-surface
Usage
HTML Structure
<div class="mdc-menu-surface">
...
</div>
Styles
@use "@material/menu-surface/mdc-menu-surface";
JavaScript Instantiation
import {MDCMenuSurface} from '@material/menu-surface';
const menuSurface = new MDCMenuSurface(document.querySelector('.mdc-menu-surface'));
See Importing the JS component for more information on how to import JavaScript.
Variants
Anchors and Positioning
Anchored To Parent
The menu surface can be positioned to automatically anchor to a parent element when opened.
<div id="toolbar" class="toolbar mdc-menu-surface--anchor">
<div class="mdc-menu-surface">
...
</div>
</div>
Anchor To Element Within Wrapper
The menu surface can be positioned to automatically anchor to another element, by wrapping the other element with the anchor class.
<div class="mdc-menu-surface--anchor">
<button id="menu-surface-button">Open Menu Surface</button>
<div class="mdc-menu-surface">
...
</div>
</div>
Fixed Position
The menu surface can use fixed positioning when being displayed.
<div class="mdc-menu-surface mdc-menu-surface--fixed">
...
</div>
Or in JS:
menuSurface.setFixedPosition(true);
Absolute Position
The menu surface can use absolute positioning when being displayed. This requires that the element containing the
menu has the position: relative
style.
<div class="mdc-menu-surface">
...
</div>
menuSurface.setAbsolutePosition(100, 100);
Style Customization
CSS Classes
CSS Class | Description |
---|
mdc-menu-surface | Mandatory. |
mdc-menu-surface--animating-open | Indicates the menu surface is currently animating open. This class is removed once the animation completes. |
mdc-menu-surface--open | Indicates the menu surface is currently open, or is currently animating open. |
mdc-menu-surface--animating-closed | Indicates the menu surface is currently animating closed. This class is removed once the animation completes. |
mdc-menu-surface--anchor | Used to indicate which element the menu should be anchored to. |
mdc-menu-surface--fixed | Used to indicate that the menu is using fixed positioning. |
mdc-menu-surface--fullwidth | Sets the menu-surface's width to match that of its parent anchor. Do not use with mdc-menu-surface--fixed or if hoisting to body. |
Sass Mixins
Mixin | Description |
---|
ink-color($color) | Sets the color property of the mdc-menu-surface . |
fill-color($color) | Sets the background-color property of the mdc-menu-surface . |
shape-radius($radius, $rtl-reflexive) | Sets the rounded shape to menu surface with given radius size. Set $rtl-reflexive to true to flip radius values in RTL context, defaults to false. |
Constants & Types
Constant Name | Description |
---|
Corner | Enum for representing an element corner for positioning the menu-surface. See constants.ts. |
Type Name | Description |
---|
MDCMenuDimensions | Width/height of an element. See types.ts. |
MDCMenuDistance | Margin values representing the distance from anchor point that the menu surface should be shown. See types.ts. |
MDCMenuPoint | X/Y coordinates. See types.ts. |
MDCMenuSurface
Properties and Methods
Property | Value Type | Description |
---|
quickOpen | boolean | Proxies to the foundation's setQuickOpen() method. |
anchorElement | Element | Gets or sets the element that the surface is anchored to, or null if the surface is not anchored. Defaults to the root element's parent mdc-menu-surface--anchor element if present. |
Method Signature | Description |
---|
isOpen() => boolean | Proxies to the foundation's isOpen method. |
open() => void | Proxies to the foundation's open method. |
close(skipRestoreFocus: boolean) => void | Proxies to the foundation's close method. |
setAnchorCorner(Corner) => void | Proxies to the foundation's setAnchorCorner(Corner) method. |
setAnchorMargin(Partial<MDCMenuDistance>) => void | Proxies to the foundation's setAnchorMargin(Partial<MDCMenuDistance>) method. |
setFixedPosition(isFixed: boolean) => void | Adds the mdc-menu-surface--fixed class to the mdc-menu-surface element. Proxies to the foundation's setIsHoisted() and setFixedPosition() methods. |
setAbsolutePosition(x: number, y: number) => void | Proxies to the foundation's setAbsolutePosition(x, y) method. Used to set the absolute x/y position of the menu on the page. Should only be used when the menu is hoisted to the body. |
setMenuSurfaceAnchorElement(element: Element) => void | Sets the element used as an anchor for menu-surface positioning logic. |
setIsHoisted() => void | Proxies to the foundation's setIsHoisted method. |
getDefaultFoundation() => MDCMenuSurfaceFoundation | Returns the foundation. |
Events
Event Name | Data | Description |
---|
MDCMenuSurface:closed | none | Event emitted after the menu surface is closed. |
MDCMenuSurface:closing | none | Event emitted when the menu surface is closing, but animation may not have completed yet. |
MDCMenuSurface:opened | none | Event emitted after the menu surface is opened. |
Usage Within Frameworks
If you are using a JavaScript framework, such as React or Angular, you can create a Menu Surface for your framework. Depending on your needs, you can use the Simple Approach: Wrapping MDC Web Vanilla Components, or the Advanced Approach: Using Foundations and Adapters. Please follow the instructions here.
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. |
hasAnchor: () => boolean | Returns whether the menu surface has an anchor for positioning. |
notifyClose() => void | Dispatches an event notifying listeners that the menu surface has been closed. |
notifyOpen() => void | Dispatches an event notifying listeners that the menu surface has been opened. |
isElementInContainer(el: Element) => boolean | Returns true if the el Element is inside the mdc-menu-surface container. |
isRtl() => boolean | Returns boolean indicating whether the current environment is RTL. |
setTransformOrigin(value: string) => void | Sets the transform origin for the menu surface element. |
isFocused() => boolean | Returns a boolean value indicating whether the root element of the menu surface is focused. |
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. |
getInnerDimensions() => MDCMenuDimensions | Returns an object with the items container width and height. |
getAnchorDimensions() => ClientRect | null | Returns an object with the dimensions and position of the anchor. |
getBodyDimensions() => MDCMenuDimensions | Returns an object with width and height of the body, in pixels. |
getWindowDimensions() => MDCMenuDimensions | Returns an object with width and height of the viewport, in pixels. |
getWindowScroll() => MDCMenuPoint | Returns an object with the amount the body has been scrolled on the x and y axis. |
setPosition(position: Partial<MDCMenuDistance>) => void | Sets the position of the menu surface element. |
setMaxHeight(value: string) => void | Sets max-height style for the menu surface element. |
Method Signature | Description |
---|
setAnchorCorner(corner: Corner) => void | Sets the corner that the menu surface will be anchored to. See constants.ts |
setAnchorMargin(margin: Partial<MDCMenuDistance>) => void | Sets the distance from the anchor point that the menu surface should be shown. |
setIsHoisted(isHoisted: boolean) => void | Sets whether the menu surface has been hoisted to the body so that the offsets are calculated relative to the page and not the anchor. |
setFixedPosition(isFixed: boolean) => void | Sets whether the menu surface is using fixed positioning. |
setAbsolutePosition(x: number, y: number) => void | Sets the absolute x/y position of the menu. Should only be used when the menu is hoisted or using fixed positioning. |
handleBodyClick(event: MouseEvent) => void | Method used as the callback function for the click event. |
handleKeydown(event: KeyboardEvent) => void | Method used as the callback function for the keydown events. |
open() => void | Opens the menu surface. |
close() => void | Closes the menu. |
isOpen() => boolean | Returns a boolean indicating whether the menu surface is open. |
setQuickOpen(quickOpen: boolean) => void | Sets whether the menu surface should open and close without animation when the open /close methods are called. |
13.0.0 (2021-09-24)
Bug Fixes
- Fix missing $ripple-target param for ripple mixin (1340ee9)
- banner: Adjusting theme api selectors to use
mdc-button
. (15981e9) - banner: Correcting incorrect theme values passed through to button's
theme-mixin
. (0de2f2e) - banner: exclude source from npm package (#7381) (d48a017), closes #7360
- banner: Removing
action-<state>-label-text-color
values from MDC light-theme
map. (d97f8f1) - button: cleanup outlined button theme keys (28d0d75)
- button: fix touch target reset in context of link buttons (3b8d442)
- button: remove negative padding around icons (d470693)
- button: remove rem/em transformers from typography theme-styles (a395972)
- button: stack ripple behind content (e1e69fd)
- density: typo in variable exports (6df682e)
- dom: Support providing an owner document for announcer messages. (6236f35)
- elevation: reduce warnings when not providing elevation tokens (adb9f1a)
- iconbutton: Fix icon button theme keys/light theme values based on updated tokens. (42d175e)
- menu: apply elevation overlay to new lists (0ad12ed)
- sass: Wrap templated calc expressions in strings (818f4ee), closes #7391
- slider: Reorder such that dragstart event is emitted before any other events when handling drag start. (877e3fb)
- slider: Replace
innerHTML
with firstChild
(37d4db8) - Fix compilation issues with TypeScript 4.4 (7246447)
- switch: add pointer cursor (12f5622)
- switch: distribute correct css (#7292) (7b6bcb8)
- switch: elevation theme custom properties not working (2865629)
- switch: use correct colors for icons in all HCM themes (d86fb6f)
- theme: ensure state selectors negate properly (7249a30)
- tooltip: Add a getActiveElement() method to MDCTooltipAdapter to delegate getting the active element from the correct document. (e334676)
- tooltip: Adjust tooltip
focusout
handler. Ensures that interactive tooltips remain open when ChromeVox uses linear navigation to read non-focusable content inside the tooltip. (7c96e6b) - tooltip: non-persistent tooltips disappear on scroll (1f9259b)
- update combined mdc package to use new switch CSS (077dcfc), closes #7304
- tooltip: allow the Mac zoom service to access plain tooltip contents (510cf90)
Code Refactoring
- fab: Deprecate legacy Fab theme mixins (83bdd02)
- iconbutton: Forward only theme mixins from MDC icon button index module. (0a90693)
- theme: Rename validate-keys() to validate-theme() (2fb068f)
Features
- button: add custom props to outlined button theme-styles (bf405d2)
- button: add custom props to protected button theme-styles (4ca11fe)
- button: add custom props to text button theme-styles (3dd6110)
- button: add missing transitions to box-shadow/border (3b92903)
- button: add static-styles-without-ripple for MWC consumption (f4241a4)
- button: add theme mixin that emits custom properties instead (4c40586)
- button: emit custom properties fill button theme-styles (a80c8b2)
- button: m3 elevation + icon base theme modules (2da3606)
- button: resolve elevation keys in theme mixin (843342f)
- chips: Add theming Sass mixin to MDC Filter Chip (8390093)
- chips: Add theming Sass mixin to MDC input & suggestion Chip (860ad06)
- chips: Added theme mixins to Assist Chip (d4e16a6)
- chips: Export all non-deprecated members through chips index (8647986)
- chips: Rename action's exported members to avoid naming collisions (b49359c)
- chips: Rename chip set's exported members to avoid naming collisions (13db34b)
- chips: Rename chip's exported members to avoid naming collisions (470bd34)
- data-table: Implement row click feature to MDC data table (8de07c0)
- data-table: use new select + list templates for pagination (08398f8)
- dialog: Add theme styles mixin to dialog (21ece53)
- dialog: Separate static styles from dialog core-styles mixin (43d2eed)
- fab: create theming file for small fabs (d082790)
- fab: prepare fab-extended for theming in MWC (ce25bc3)
- iconbutton: Add
.mdc-icon-button--display-flex
class that centers icon via flexbox. When using the new theme API, the icon button should have this class. (8355e14) - iconbutton: Add MDC theme mixin that declares custom properties. (fa7520f)
- iconbutton: Add theme styles mixin. (65aa63b)
- menu: Added getter method to check fixed position status of menu (fb76c50)
- menu: Adds option to prevent focus from being restored after an item action. (65084ba)
- select: start compatibility work for evolution lists (e8554db)
- theme: Added
validate-theme-keys()
mixin to validate theme keys only (457d89a)
BREAKING CHANGES
PiperOrigin-RevId: 398575780
- iconbutton: MDC iconbutton
_index
Sass module will only export theme mixins.
PiperOrigin-RevId: 391773229
- theme: Renamed Sass mixins
validate-keys()
to validate-theme()
in @material/theme
PiperOrigin-RevId: 390671152
- fab: Renamed Fab's mixins to deprecate legacy theme mixins.
PiperOrigin-RevId: 387378201