Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Menu] Support Cascading Menus #20591

Closed
wants to merge 13 commits into from
14 changes: 13 additions & 1 deletion docs/pages/api-docs/menu-item.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,23 @@
"disableGutters": { "type": { "name": "bool" } },
"divider": { "type": { "name": "bool" } },
"focusVisibleClassName": { "type": { "name": "string" } },
"openSubMenu": { "type": { "name": "bool" } },
"subMenu": { "type": { "name": "node" } },
"subMenuIcon": { "type": { "name": "node" }, "default": "KeyboardArrowRight" },
"sx": { "type": { "name": "union", "description": "func<br>&#124;&nbsp;object" } }
},
"name": "MenuItem",
"styles": {
"classes": ["root", "focusVisible", "dense", "disabled", "divider", "gutters", "selected"],
"classes": [
"root",
"focusVisible",
"dense",
"disabled",
"divider",
"gutters",
"selected",
"openSubMenuParent"
],
"globalClasses": {
"focusVisible": "Mui-focusVisible",
"disabled": "Mui-disabled",
Expand Down
19 changes: 19 additions & 0 deletions docs/pages/api-docs/sub-menu.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import * as React from 'react';
import ApiPage from 'docs/src/modules/components/ApiPage';
import mapApiPageTranslations from 'docs/src/modules/utils/mapApiPageTranslations';
import jsonPageContent from './sub-menu.json';

export default function Page(props) {
const { descriptions, pageContent } = props;
return <ApiPage descriptions={descriptions} pageContent={pageContent} />;
}

Page.getInitialProps = () => {
const req = require.context('docs/translations/api-docs/sub-menu', false, /sub-menu.*.json$/);
const descriptions = mapApiPageTranslations(req);

return {
descriptions,
pageContent: jsonPageContent,
};
};
10 changes: 10 additions & 0 deletions docs/pages/api-docs/sub-menu.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"props": { "children": { "type": { "name": "node" } } },
"name": "SubMenu",
"styles": { "classes": [], "globalClasses": {}, "name": null },
"spread": true,
"filename": "/packages/mui-material/src/SubMenu/SubMenu.js",
"inheritance": null,
"demos": "<ul><li><a href=\"/components/menus/\">Menus</a></li></ul>",
"cssComponent": false
}
65 changes: 65 additions & 0 deletions docs/src/pages/components/menus/CascadingMenu.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
import React, { useState } from 'react';
import Button from '@mui/material/Button';
import Menu from '@mui/material/Menu';
import MenuItem from '@mui/material/MenuItem';
import SubMenu from '@mui/material/SubMenu';
import useTheme from '@mui/styles/useTheme';

export default function CascadingMenu() {
const theme = useTheme();
const [anchorEl, setAnchorEl] = useState(null);

const handleButtonClick = (event) => {
setAnchorEl(event.currentTarget);
};

const handleClose = () => {
setAnchorEl(null);
};

return (
<div>
<Button
aria-controls="cascading-menu"
aria-haspopup="true"
onClick={handleButtonClick}
>
Open Menu
</Button>
<Menu
id="cascading-menu"
anchorEl={anchorEl}
anchorOrigin={{
vertical: 'top',
horizontal: theme.direction === 'rtl' ? 'left' : 'right',
}}
open={Boolean(anchorEl)}
onClose={handleClose}
>
<MenuItem
subMenu={
<SubMenu>
<MenuItem onClick={handleClose}>View</MenuItem>
<MenuItem
subMenu={
<SubMenu>
<MenuItem onClick={handleClose}>75%</MenuItem>
<MenuItem onClick={handleClose}>100%</MenuItem>
<MenuItem onClick={handleClose}>125%</MenuItem>
</SubMenu>
}
>
Zoom
</MenuItem>
<MenuItem onClick={handleClose}>Help</MenuItem>
</SubMenu>
}
>
Options
</MenuItem>
<MenuItem onClick={handleClose}>My account</MenuItem>
<MenuItem onClick={handleClose}>Logout</MenuItem>
</Menu>
</div>
);
}
10 changes: 8 additions & 2 deletions docs/src/pages/components/menus/menus.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
title: React Menu component
components: Menu, MenuItem, MenuList, ClickAwayListener, Popover, Popper
components: Menu, SubMenu, MenuItem, MenuList, ClickAwayListener, Popover, Popper
githubLabel: 'component: Menu'
materialDesign: https://material.io/components/menus
waiAria: https://www.w3.org/TR/wai-aria-practices/#menubutton
Expand Down Expand Up @@ -67,7 +67,13 @@ The primary responsibility of the `MenuList` component is to handle the focus.

{{"demo": "pages/components/menus/AccountMenu.js"}}

## Customization
## Cascading menu

Cascading menus allow users to choose from a large variety of choices, by displaying menus with multiple levels of hierarchy.

{{"demo": "pages/components/menus/CascadingMenu.js"}}

## Customized menus

Here is an example of customizing the component.
You can learn more about this in the [overrides documentation page](/customization/how-to-customize/).
Expand Down
1 change: 1 addition & 0 deletions docs/src/pagesApi.js
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,7 @@ module.exports = [
{ pathname: '/api-docs/step-icon' },
{ pathname: '/api-docs/step-label' },
{ pathname: '/api-docs/stepper' },
{ pathname: '/api-docs/sub-menu' },
{ pathname: '/api-docs/svg-icon' },
{ pathname: '/api-docs/swipeable-drawer' },
{ pathname: '/api-docs/switch' },
Expand Down
8 changes: 8 additions & 0 deletions docs/translations/api-docs/menu-item/menu-item.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@
"disableGutters": "If <code>true</code>, the left and right padding is removed.",
"divider": "If <code>true</code>, a 1px light border is added to the bottom of the menu item.",
"focusVisibleClassName": "This prop can help identify which element has keyboard focus. The class name will be applied when the element gains the focus through keyboard interaction. It&#39;s a polyfill for the <a href=\"https://drafts.csswg.org/selectors-4/#the-focus-visible-pseudo\">CSS :focus-visible selector</a>. The rationale for using this feature <a href=\"https://github.com/WICG/focus-visible/blob/master/explainer.md\">is explained here</a>. A <a href=\"https://github.com/WICG/focus-visible\">polyfill can be used</a> to apply a <code>focus-visible</code> class to other components if needed.",
"openSubMenu": "When <code>true</code>, opens the subMenu, if provided.",
"subMenu": "Menu to display as a sub-menu.",
"subMenuIcon": "Normally <code>Icon</code>, <code>SvgIcon</code>, or a <code>@material-ui/icons</code> SVG icon element rendered on a MenuItem that contains a subMenu",
"sx": "The system prop that allows defining system overrides as well as additional CSS styles. See the <a href=\"/system/the-sx-prop/\">`sx` page</a> for more details."
},
"classDescriptions": {
Expand Down Expand Up @@ -42,6 +45,11 @@
"description": "State class applied to {{nodeName}} if {{conditions}}.",
"nodeName": "the root element",
"conditions": "<code>selected={true}</code>"
},
"openSubMenuParent": {
"description": "State class applied to {{nodeName}} if {{conditions}}.",
"nodeName": "the root element",
"conditions": "its submenu is open"
}
}
}
5 changes: 5 additions & 0 deletions docs/translations/api-docs/sub-menu/sub-menu-de.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"componentDescription": "",
"propDescriptions": { "children": "Menu contents, normally <code>MenuItem</code>s." },
"classDescriptions": {}
}
5 changes: 5 additions & 0 deletions docs/translations/api-docs/sub-menu/sub-menu-es.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"componentDescription": "",
"propDescriptions": { "children": "Menu contents, normally <code>MenuItem</code>s." },
"classDescriptions": {}
}
5 changes: 5 additions & 0 deletions docs/translations/api-docs/sub-menu/sub-menu-fr.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"componentDescription": "",
"propDescriptions": { "children": "Menu contents, normally <code>MenuItem</code>s." },
"classDescriptions": {}
}
5 changes: 5 additions & 0 deletions docs/translations/api-docs/sub-menu/sub-menu-ja.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"componentDescription": "",
"propDescriptions": { "children": "Menu contents, normally <code>MenuItem</code>s." },
"classDescriptions": {}
}
5 changes: 5 additions & 0 deletions docs/translations/api-docs/sub-menu/sub-menu-pt.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"componentDescription": "",
"propDescriptions": { "children": "Menu contents, normally <code>MenuItem</code>s." },
"classDescriptions": {}
}
5 changes: 5 additions & 0 deletions docs/translations/api-docs/sub-menu/sub-menu-ru.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"componentDescription": "",
"propDescriptions": { "children": "Menu contents, normally <code>MenuItem</code>s." },
"classDescriptions": {}
}
5 changes: 5 additions & 0 deletions docs/translations/api-docs/sub-menu/sub-menu-zh.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"componentDescription": "",
"propDescriptions": { "children": "Menu contents, normally <code>MenuItem</code>s." },
"classDescriptions": {}
}
5 changes: 5 additions & 0 deletions docs/translations/api-docs/sub-menu/sub-menu.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"componentDescription": "",
"propDescriptions": { "children": "Menu contents, normally <code>MenuItem</code>s." },
"classDescriptions": {}
}
1 change: 1 addition & 0 deletions packages/mui-material/src/Menu/Menu.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ export interface MenuProps extends StandardProps<PopoverProps> {
* `classes` prop applied to the [`Popover`](/api/popover/) element.
*/
PopoverClasses?: PopoverProps['classes'];
setParentOpenSubMenuIndex?: (index: number) => void;
/**
* The system prop that allows defining system overrides as well as additional CSS styles.
*/
Expand Down