Reference

Menu
Menus present a selection of options on temporary surfaces.
A menu showcases a list of options on a transient surface, appearing when a user engages with a button or another control.
Introduction
Menus are constructed using a set of interconnected components:
- Menu: The container or surface that holds the menu.
- Menu Item: An individual option available for user selection within the menu.
- Menu List (optional): An alternative, composable container for Menu Items—refer to Composition with Menu List for more information.
Basic menu
By default, a basic menu appears over its anchor element (this behavior can be adjusted via props). When near a screen edge, it realigns vertically to ensure all menu items are fully visible.
The component should be set up so that choosing an option immediately confirms the selection and closes the menu, as demonstrated below.
import * as React from 'react'; import Button from '@mui/material/Button'; import Menu from '@mui/material/Menu'; import MenuItem from '@mui/material/MenuItem'; export default function BasicMenu() { const [anchorEl, setAnchorEl] = React.useState<null | HTMLElement>(null); const open = Boolean(anchorEl); const handleClick = (event: React.MouseEvent<HTMLButtonElement>) => { setAnchorEl(event.currentTarget); }; const handleClose = () => { setAnchorEl(null); }; return ( <div> <Button id="basic-button" aria-controls={open ? 'basic-menu' : undefined} aria-haspopup="true" aria-expanded={open ? 'true' : undefined} onClick={handleClick} > Dashboard </Button> <Menu id="basic-menu" anchorEl={anchorEl} open={open} onClose={handleClose} MenuListProps={{ 'aria-labelledby': 'basic-button', }} > <MenuItem onClick={handleClose}>Profile</MenuItem> <MenuItem onClick={handleClose}>My account</MenuItem> <MenuItem onClick={handleClose}>Logout</MenuItem> </Menu> </div> ); }
Icon menu
In desktop viewports, the menu's padding is expanded to provide additional space.
- Cut
⌘X
- Copy
⌘C
- Paste
⌘V
- Web Clipboard
import * as React from 'react'; import Divider from '@mui/material/Divider'; import Paper from '@mui/material/Paper'; import MenuList from '@mui/material/MenuList'; import MenuItem from '@mui/material/MenuItem'; import ListItemText from '@mui/material/ListItemText'; import ListItemIcon from '@mui/material/ListItemIcon'; import Typography from '@mui/material/Typography'; import ContentCut from '@mui/icons-material/ContentCut'; import ContentCopy from '@mui/icons-material/ContentCopy'; import ContentPaste from '@mui/icons-material/ContentPaste'; import Cloud from '@mui/icons-material/Cloud'; export default function IconMenu() { return ( <Paper sx={{ width: 320, maxWidth: '100%' }}> <MenuList> <MenuItem> <ListItemIcon> <ContentCut fontSize="small" /> </ListItemIcon> <ListItemText>Cut</ListItemText> <Typography variant="body2" sx={{ color: 'text.secondary' }}> ⌘X </Typography> </MenuItem> <MenuItem> <ListItemIcon> <ContentCopy fontSize="small" /> </ListItemIcon> <ListItemText>Copy</ListItemText> <Typography variant="body2" sx={{ color: 'text.secondary' }}> ⌘C </Typography> </MenuItem> <MenuItem> <ListItemIcon> <ContentPaste fontSize="small" /> </ListItemIcon> <ListItemText>Paste</ListItemText> <Typography variant="body2" sx={{ color: 'text.secondary' }}> ⌘V </Typography> </MenuItem> <Divider /> <MenuItem> <ListItemIcon> <Cloud fontSize="small" /> </ListItemIcon> <ListItemText>Web Clipboard</ListItemText> </MenuItem> </MenuList> </Paper> ); }
Dense menu
For menus with lengthy lists or extended text, the
dense
prop can be used to minimize padding and font size.- Single
- 1.15
- Double
- Custom: 1.2
- Add space before paragraph
- Add space after paragraph
- Custom spacing...
import * as React from 'react'; import Paper from '@mui/material/Paper'; import Divider from '@mui/material/Divider'; import MenuList from '@mui/material/MenuList'; import MenuItem from '@mui/material/MenuItem'; import ListItemIcon from '@mui/material/ListItemIcon'; import ListItemText from '@mui/material/ListItemText'; import Check from '@mui/icons-material/Check'; export default function DenseMenu() { return ( <Paper sx={{ width: 320 }}> <MenuList dense> <MenuItem> <ListItemText inset>Single</ListItemText> </MenuItem> <MenuItem> <ListItemText inset>1.15</ListItemText> </MenuItem> <MenuItem> <ListItemText inset>Double</ListItemText> </MenuItem> <MenuItem> <ListItemIcon> <Check /> </ListItemIcon> Custom: 1.2 </MenuItem> <Divider /> <MenuItem> <ListItemText>Add space before paragraph</ListItemText> </MenuItem> <MenuItem> <ListItemText>Add space after paragraph</ListItemText> </MenuItem> <Divider /> <MenuItem> <ListItemText>Custom spacing...</ListItemText> </MenuItem> </MenuList> </Paper> ); }
Selected menu
When used for item selection, simple menus focus on the selected menu item upon opening. The selected item is defined using the
selected
prop (from ListItem). To use a selected item without affecting initial focus, set the variant
prop to "menu".import * as React from 'react'; import List from '@mui/material/List'; import ListItemButton from '@mui/material/ListItemButton'; import ListItemText from '@mui/material/ListItemText'; import MenuItem from '@mui/material/MenuItem'; import Menu from '@mui/material/Menu'; const options = [ 'Show some love to MUI', 'Show all notification content', 'Hide sensitive notification content', 'Hide all notification content', ]; export default function SimpleListMenu() { const [anchorEl, setAnchorEl] = React.useState<null | HTMLElement>(null); const [selectedIndex, setSelectedIndex] = React.useState(1); const open = Boolean(anchorEl); const handleClickListItem = (event: React.MouseEvent<HTMLElement>) => { setAnchorEl(event.currentTarget); }; const handleMenuItemClick = ( event: React.MouseEvent<HTMLElement>, index: number, ) => { setSelectedIndex(index); setAnchorEl(null); }; const handleClose = () => { setAnchorEl(null); }; return ( <div> <List component="nav" aria-label="Device settings" sx={{ bgcolor: 'background.paper' }} > <ListItemButton id="lock-button" aria-haspopup="listbox" aria-controls="lock-menu" aria-label="when device is locked" aria-expanded={open ? 'true' : undefined} onClick={handleClickListItem} > <ListItemText primary="When device is locked" secondary={options[selectedIndex]} /> </ListItemButton> </List> <Menu id="lock-menu" anchorEl={anchorEl} open={open} onClose={handleClose} MenuListProps={{ 'aria-labelledby': 'lock-button', role: 'listbox', }} > {options.map((option, index) => ( <MenuItem key={option} disabled={index === 0} selected={index === selectedIndex} onClick={(event) => handleMenuItemClick(event, index)} > {option} </MenuItem> ))} </Menu> </div> ); }
Positioned menu
Since the
Menu
component leverages the Popover
component for positioning, you can utilize the same positioning props to adjust its placement. For example, you can position the menu above the anchor.import * as React from 'react'; import Button from '@mui/material/Button'; import Menu from '@mui/material/Menu'; import MenuItem from '@mui/material/MenuItem'; export default function PositionedMenu() { const [anchorEl, setAnchorEl] = React.useState<null | HTMLElement>(null); const open = Boolean(anchorEl); const handleClick = (event: React.MouseEvent<HTMLElement>) => { setAnchorEl(event.currentTarget); }; const handleClose = () => { setAnchorEl(null); }; return ( <div> <Button id="demo-positioned-button" aria-controls={open ? 'demo-positioned-menu' : undefined} aria-haspopup="true" aria-expanded={open ? 'true' : undefined} onClick={handleClick} > Dashboard </Button> <Menu id="demo-positioned-menu" aria-labelledby="demo-positioned-button" anchorEl={anchorEl} open={open} onClose={handleClose} anchorOrigin={{ vertical: 'top', horizontal: 'left', }} transformOrigin={{ vertical: 'top', horizontal: 'left', }} > <MenuItem onClick={handleClose}>Profile</MenuItem> <MenuItem onClick={handleClose}>My account</MenuItem> <MenuItem onClick={handleClose}>Logout</MenuItem> </Menu> </div> ); }
Composition with Menu List
The
Menu
component internally uses the Popover
component. However, you may prefer an alternative positioning approach or want to avoid blocking scrolling.The
MenuList
component enables custom menu composition for such scenarios, primarily handling focus management. The example below demonstrates composition using MenuList
with a Popper
component instead of the default Popover
.- Profile
- My account
- Logout
import * as React from 'react'; import Button from '@mui/material/Button'; import ClickAwayListener from '@mui/material/ClickAwayListener'; import Grow from '@mui/material/Grow'; import Paper from '@mui/material/Paper'; import Popper from '@mui/material/Popper'; import MenuItem from '@mui/material/MenuItem'; import MenuList from '@mui/material/MenuList'; import Stack from '@mui/material/Stack'; export default function MenuListComposition() { const [open, setOpen] = React.useState(false); const anchorRef = React.useRef<HTMLButtonElement>(null); const handleToggle = () => { setOpen((prevOpen) => !prevOpen); }; const handleClose = (event: Event | React.SyntheticEvent) => { if ( anchorRef.current && anchorRef.current.contains(event.target as HTMLElement) ) { return; } setOpen(false); }; function handleListKeyDown(event: React.KeyboardEvent) { if (event.key === 'Tab') { event.preventDefault(); setOpen(false); } else if (event.key === 'Escape') { setOpen(false); } } // Restore focus to the button when transitioning from closed to open const prevOpen = React.useRef(open); React.useEffect(() => { if (prevOpen.current === true && open === false) { anchorRef.current!.focus(); } prevOpen.current = open; }, [open]); return ( <Stack direction="row" spacing={2}> <Paper> <MenuList> <MenuItem>Profile</MenuItem> <MenuItem>My account</MenuItem> <MenuItem>Logout</MenuItem> </MenuList> </Paper> <div> <Button ref={anchorRef} id="composition-button" aria-controls={open ? 'composition-menu' : undefined} aria-expanded={open ? 'true' : undefined} aria-haspopup="true" onClick={handleToggle} > Dashboard </Button> <Popper open={open} anchorEl={anchorRef.current} role={undefined} placement="bottom-start" transition disablePortal > {({ TransitionProps, placement }) => ( <Grow {...TransitionProps} style={{ transformOrigin: placement === 'bottom-start' ? 'left top' : 'left bottom', }} > <Paper> <ClickAwayListener onClickAway={handleClose}> <MenuList autoFocusItem={open} id="composition-menu" aria-labelledby="composition-button" onKeyDown={handleListKeyDown} > <MenuItem onClick={handleClose}>Profile</MenuItem> <MenuItem onClick={handleClose}>My account</MenuItem> <MenuItem onClick={handleClose}>Logout</MenuItem> </MenuList> </ClickAwayListener> </Paper> </Grow> )} </Popper> </div> </Stack> ); }
Account menu
The content of a
Menu
can be combined with other components, such as Avatar
.Contact
Profile
import * as React from 'react'; import Box from '@mui/material/Box'; import Avatar from '@mui/material/Avatar'; import Menu from '@mui/material/Menu'; import MenuItem from '@mui/material/MenuItem'; import ListItemIcon from '@mui/material/ListItemIcon'; import Divider from '@mui/material/Divider'; import IconButton from '@mui/material/IconButton'; import Typography from '@mui/material/Typography'; import Tooltip from '@mui/material/Tooltip'; import PersonAdd from '@mui/icons-material/PersonAdd'; import Settings from '@mui/icons-material/Settings'; import Logout from '@mui/icons-material/Logout'; export default function AccountMenu() { const [anchorEl, setAnchorEl] = React.useState<null | HTMLElement>(null); const open = Boolean(anchorEl); const handleClick = (event: React.MouseEvent<HTMLElement>) => { setAnchorEl(event.currentTarget); }; const handleClose = () => { setAnchorEl(null); }; return ( <React.Fragment> <Box sx={{ display: 'flex', alignItems: 'center', textAlign: 'center' }}> <Typography sx={{ minWidth: 100 }}>Contact</Typography> <Typography sx={{ minWidth: 100 }}>Profile</Typography> <Tooltip title="Account settings"> <IconButton onClick={handleClick} size="small" sx={{ ml: 2 }} aria-controls={open ? 'account-menu' : undefined} aria-haspopup="true" aria-expanded={open ? 'true' : undefined} > <Avatar sx={{ width: 32, height: 32 }}>M</Avatar> </IconButton> </Tooltip> </Box> <Menu anchorEl={anchorEl} id="account-menu" open={open} onClose={handleClose} onClick={handleClose} slotProps={{ paper: { elevation: 0, sx: { overflow: 'visible', filter: 'drop-shadow(0px 2px 8px rgba(0,0,0,0.32))', mt: 1.5, '& .MuiAvatar-root': { width: 32, height: 32, ml: -0.5, mr: 1, }, '&::before': { content: '""', display: 'block', position: 'absolute', top: 0, right: 14, width: 10, height: 10, bgcolor: 'background.paper', transform: 'translateY(-50%) rotate(45deg)', zIndex: 0, }, }, }, }} transformOrigin={{ horizontal: 'right', vertical: 'top' }} anchorOrigin={{ horizontal: 'right', vertical: 'bottom' }} > <MenuItem onClick={handleClose}> <Avatar /> Profile </MenuItem> <MenuItem onClick={handleClose}> <Avatar /> My account </MenuItem> <Divider /> <MenuItem onClick={handleClose}> <ListItemIcon> <PersonAdd fontSize="small" /> </ListItemIcon> Add another account </MenuItem> <MenuItem onClick={handleClose}> <ListItemIcon> <Settings fontSize="small" /> </ListItemIcon> Settings </MenuItem> <MenuItem onClick={handleClose}> <ListItemIcon> <Logout fontSize="small" /> </ListItemIcon> Logout </MenuItem> </Menu> </React.Fragment> ); }
Customization
This example illustrates how to customize the component. Learn more in the overrides documentation page.
import * as React from 'react'; import { styled, alpha } from '@mui/material/styles'; import Button from '@mui/material/Button'; import Menu, { MenuProps } from '@mui/material/Menu'; import MenuItem from '@mui/material/MenuItem'; import EditIcon from '@mui/icons-material/Edit'; import Divider from '@mui/material/Divider'; import ArchiveIcon from '@mui/icons-material/Archive'; import FileCopyIcon from '@mui/icons-material/FileCopy'; import MoreHorizIcon from '@mui/icons-material/MoreHoriz'; import KeyboardArrowDownIcon from '@mui/icons-material/KeyboardArrowDown'; const StyledMenu = styled((props: MenuProps) => ( <Menu elevation={0} anchorOrigin={{ vertical: 'bottom', horizontal: 'right', }} transformOrigin={{ vertical: 'top', horizontal: 'right', }} {...props} /> ))(({ theme }) => ({ '& .MuiPaper-root': { borderRadius: 6, marginTop: theme.spacing(1), minWidth: 180, color: 'rgb(55, 65, 81)', boxShadow: 'rgb(255, 255, 255) 0px 0px 0px 0px, rgba(0, 0, 0, 0.05) 0px 0px 0px 1px, rgba(0, 0, 0, 0.1) 0px 10px 15px -3px, rgba(0, 0, 0, 0.05) 0px 4px 6px -2px', '& .MuiMenu-list': { padding: '4px 0', }, '& .MuiMenuItem-root': { '& .MuiSvgIcon-root': { fontSize: 18, color: theme.palette.text.secondary, marginRight: theme.spacing(1.5), }, '&:active': { backgroundColor: alpha( theme.palette.primary.main, theme.palette.action.selectedOpacity, ), }, }, ...theme.applyStyles('dark', { color: theme.palette.grey[300], }), }, })); export default function CustomizedMenus() { const [anchorEl, setAnchorEl] = React.useState<null | HTMLElement>(null); const open = Boolean(anchorEl); const handleClick = (event: React.MouseEvent<HTMLElement>) => { setAnchorEl(event.currentTarget); }; const handleClose = () => { setAnchorEl(null); }; return ( <div> <Button id="demo-customized-button" aria-controls={open ? 'demo-customized-menu' : undefined} aria-haspopup="true" aria-expanded={open ? 'true' : undefined} variant="contained" disableElevation onClick={handleClick} endIcon={<KeyboardArrowDownIcon />} > Options </Button> <StyledMenu id="demo-customized-menu" MenuListProps={{ 'aria-labelledby': 'demo-customized-button', }} anchorEl={anchorEl} open={open} onClose={handleClose} > <MenuItem onClick={handleClose} disableRipple> <EditIcon /> Edit </MenuItem> <MenuItem onClick={handleClose} disableRipple> <FileCopyIcon /> Duplicate </MenuItem> <Divider sx={{ my: 0.5 }} /> <MenuItem onClick={handleClose} disableRipple> <ArchiveIcon /> Archive </MenuItem> <MenuItem onClick={handleClose} disableRipple> <MoreHorizIcon /> More </MenuItem> </StyledMenu> </div> ); }
The
MenuItem
component wraps ListItem
with added styles. You can leverage the same list composition features with the MenuItem
component.🎨 For inspiration, explore MUI Treasury's customization examples.
Max height menu
When a menu's height prevents all items from being shown, it can scroll internally.
import * as React from 'react'; import IconButton from '@mui/material/IconButton'; import Menu from '@mui/material/Menu'; import MenuItem from '@mui/material/MenuItem'; import MoreVertIcon from '@mui/icons-material/MoreVert'; const options = [ 'None', 'Atria', 'Callisto', 'Dione', 'Ganymede', 'Hangouts Call', 'Luna', 'Oberon', 'Phobos', 'Pyxis', 'Sedna', 'Titania', 'Triton', 'Umbriel', ]; const ITEM_HEIGHT = 48; export default function LongMenu() { const [anchorEl, setAnchorEl] = React.useState<null | HTMLElement>(null); const open = Boolean(anchorEl); const handleClick = (event: React.MouseEvent<HTMLElement>) => { setAnchorEl(event.currentTarget); }; const handleClose = () => { setAnchorEl(null); }; return ( <div> <IconButton aria-label="more" id="long-button" aria-controls={open ? 'long-menu' : undefined} aria-expanded={open ? 'true' : undefined} aria-haspopup="true" onClick={handleClick} > <MoreVertIcon /> </IconButton> <Menu id="long-menu" MenuListProps={{ 'aria-labelledby': 'long-button', }} anchorEl={anchorEl} open={open} onClose={handleClose} slotProps={{ paper: { style: { maxHeight: ITEM_HEIGHT * 4.5, width: '20ch', }, }, }} > {options.map((option) => ( <MenuItem key={option} selected={option === 'Pyxis'} onClick={handleClose}> {option} </MenuItem> ))} </Menu> </div> ); }
Limitations
A flexbox bug prevents
text-overflow: ellipsis
from functioning in a flexbox layout. You can bypass this issue by using the Typography
component with the noWrap
prop.A short message
A very long text that overflows
A very long text that overflows
import * as React from 'react'; import MenuList from '@mui/material/MenuList'; import MenuItem from '@mui/material/MenuItem'; import Paper from '@mui/material/Paper'; import ListItemIcon from '@mui/material/ListItemIcon'; import Typography from '@mui/material/Typography'; import DraftsIcon from '@mui/icons-material/Drafts'; import SendIcon from '@mui/icons-material/Send'; import PriorityHighIcon from '@mui/icons-material/PriorityHigh'; export default function TypographyMenu() { return ( <Paper sx={{ width: 230 }}> <MenuList> <MenuItem> <ListItemIcon> <SendIcon fontSize="small" /> </ListItemIcon> <Typography variant="inherit">A short message</Typography> </MenuItem> <MenuItem> <ListItemIcon> <PriorityHighIcon fontSize="small" /> </ListItemIcon> <Typography variant="inherit">A very long text that overflows</Typography> </MenuItem> <MenuItem> <ListItemIcon> <DraftsIcon fontSize="small" /> </ListItemIcon> <Typography variant="inherit" noWrap> A very long text that overflows </Typography> </MenuItem> </MenuList> </Paper> ); }
Change transition
Apply a different transition effect.
import * as React from 'react'; import Button from '@mui/material/Button'; import Menu from '@mui/material/Menu'; import MenuItem from '@mui/material/MenuItem'; import Fade from '@mui/material/Fade'; export default function FadeMenu() { const [anchorEl, setAnchorEl] = React.useState<null | HTMLElement>(null); const open = Boolean(anchorEl); const handleClick = (event: React.MouseEvent<HTMLElement>) => { setAnchorEl(event.currentTarget); }; const handleClose = () => { setAnchorEl(null); }; return ( <div> <Button id="fade-button" aria-controls={open ? 'fade-menu' : undefined} aria-haspopup="true" aria-expanded={open ? 'true' : undefined} onClick={handleClick} > Dashboard </Button> <Menu id="fade-menu" MenuListProps={{ 'aria-labelledby': 'fade-button', }} anchorEl={anchorEl} open={open} onClose={handleClose} TransitionComponent={Fade} > <MenuItem onClick={handleClose}>Profile</MenuItem> <MenuItem onClick={handleClose}>My account</MenuItem> <MenuItem onClick={handleClose}>Logout</MenuItem> </Menu> </div> ); }
Context menu
This example demonstrates a context menu, accessible via a right-click.
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam ipsum purus, bibendum sit amet vulputate eget, porta semper ligula. Donec bibendum vulputate erat, ac fringilla mi finibus nec. Donec ac dolor sed dolor porttitor blandit vel vel purus. Fusce vel malesuada ligula. Nam quis vehicula ante, eu finibus est. Proin ullamcorper fermentum orci, quis finibus massa. Nunc lobortis, massa ut rutrum ultrices, metus metus finibus ex, sit amet facilisis neque enim sed neque. Quisque accumsan metus vel maximus consequat. Suspendisse lacinia tellus a libero volutpat maximus.
import * as React from 'react'; import Menu from '@mui/material/Menu'; import MenuItem from '@mui/material/MenuItem'; import Typography from '@mui/material/Typography'; export default function ContextMenu() { const [contextMenu, setContextMenu] = React.useState<{ mouseX: number; mouseY: number; } | null>(null); const handleContextMenu = (event: React.MouseEvent) => { event.preventDefault(); setContextMenu( contextMenu === null ? { mouseX: event.clientX + 2, mouseY: event.clientY - 6, } : // Repeated context menu actions when already open closes it in Chrome 84 on Ubuntu // Other native context menus may behave differently. // This behavior prevents the context menu from the backdrop from relocating existing context menus. null, ); // Avoid losing text selection after opening the context menu on Safari and Firefox const selection = document.getSelection(); if (selection && selection.rangeCount > 0) { const range = selection.getRangeAt(0); setTimeout(() => { selection.addRange(range); }); } }; const handleClose = () => { setContextMenu(null); }; return ( <div onContextMenu={handleContextMenu} style={{ cursor: 'context-menu' }}> <Typography> Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam ipsum purus, bibendum sit amet vulputate eget, porta semper ligula. Donec bibendum vulputate erat, ac fringilla mi finibus nec. Donec ac dolor sed dolor porttitor blandit vel vel purus. Fusce vel malesuada ligula. Nam quis vehicula ante, eu finibus est. Proin ullamcorper fermentum orci, quis finibus massa. Nunc lobortis, massa ut rutrum ultrices, metus metus finibus ex, sit amet facilisis neque enim sed neque. Quisque accumsan metus vel maximus consequat. Suspendisse lacinia tellus a libero volutpat maximus. </Typography> <Menu open={contextMenu !== null} onClose={handleClose} anchorReference="anchorPosition" anchorPosition={ contextMenu !== null ? { top: contextMenu.mouseY, left: contextMenu.mouseX } : undefined } > <MenuItem onClick={handleClose}>Copy</MenuItem> <MenuItem onClick={handleClose}>Print</MenuItem> <MenuItem onClick={handleClose}>Highlight</MenuItem> <MenuItem onClick={handleClose}>Email</MenuItem> </Menu> </div> ); }
Grouped Menu
Organize items into categories using the
ListSubheader
component.import * as React from 'react'; import Button from '@mui/material/Button'; import ListSubheader from '@mui/material/ListSubheader'; import Menu from '@mui/material/Menu'; import MenuItem from '@mui/material/MenuItem'; export default function GroupedMenu() { const [anchorEl, setAnchorEl] = React.useState<null | HTMLElement>(null); const open = Boolean(anchorEl); const handleClick = (event: React.MouseEvent<HTMLButtonElement>) => { setAnchorEl(event.currentTarget); }; const handleClose = () => { setAnchorEl(null); }; return ( <div> <Button id="basic-button" aria-controls={open ? 'grouped-menu' : undefined} aria-haspopup="true" aria-expanded={open ? 'true' : undefined} onClick={handleClick} > Dashboard </Button> <Menu id="grouped-menu" anchorEl={anchorEl} open={open} onClose={handleClose} MenuListProps={{ 'aria-labelledby': 'basic-button', }} > <ListSubheader>Category 1</ListSubheader> <MenuItem onClick={handleClose}>Option 1</MenuItem> <MenuItem onClick={handleClose}>Option 2</MenuItem> <ListSubheader>Category 2</ListSubheader> <MenuItem onClick={handleClose}>Option 3</MenuItem> <MenuItem onClick={handleClose}>Option 4</MenuItem> </Menu> </div> ); }
Supplementary projects
For advanced use cases, you can benefit from the following resources:
material-ui-popup-state
The
material-ui-popup-state
package simplifies menu state management in most scenarios.import * as React from 'react'; import Button from '@mui/material/Button'; import Menu from '@mui/material/Menu'; import MenuItem from '@mui/material/MenuItem'; import PopupState, { bindTrigger, bindMenu } from 'material-ui-popup-state'; export default function MenuPopupState() { return ( <PopupState variant="popover" popupId="demo-popup-menu"> {(popupState) => ( <React.Fragment> <Button variant="contained" {...bindTrigger(popupState)}> Dashboard </Button> <Menu {...bindMenu(popupState)}> <MenuItem onClick={popupState.close}>My Profile</MenuItem> <MenuItem onClick={popupState.close}>Account Settings</MenuItem> <MenuItem onClick={popupState.close}>Sign out</MenuItem> </Menu> </React.Fragment> )} </PopupState> ); }