Material UI is a Material Design library made for React.
It’s a set of React components that have Material Design styles.
In this article, we’ll look at how to customize menus to Material UI.
Customized Menus
We can customize our menu with our styles.
For example, we can write:
import React from "react";
import { withStyles } from "@material-ui/core/styles";
import Button from "@material-ui/core/Button";
import Menu from "@material-ui/core/Menu";
import MenuItem from "@material-ui/core/MenuItem";
import ListItemIcon from "@material-ui/core/ListItemIcon";
import ListItemText from "@material-ui/core/ListItemText";
import InboxIcon from "@material-ui/icons/MoveToInbox";
const StyledMenu = withStyles({
paper: {
border: "1px solid #d3d4d5"
}
})(props => (
<Menu
elevation={0}
getContentAnchorEl={null}
anchorOrigin={{
vertical: "bottom"
}}
transformOrigin={{
vertical: "top"
}}
{...props}
/>
));
const StyledMenuItem = withStyles(theme => ({
root: {
"&:focus": {
backgroundColor: theme.palette.primary.main,
"& .MuiListItemIcon-root, & .MuiListItemText-primary": {
color: theme.palette.common.white
}
}
}
}))(MenuItem);
export default function App() {
const [anchorEl, setAnchorEl] = React.useState(null);
const handleClick = event => {
setAnchorEl(event.currentTarget);
};
const handleClose = () => {
setAnchorEl(null);
};
return (
<div>
<Button variant="contained" color="primary" onClick={handleClick}>
Open Menu
</Button>
<StyledMenu open={Boolean(anchorEl)}>
<StyledMenuItem onClick={handleClose}>
<ListItemIcon>
<InboxIcon fontSize="small" />
</ListItemIcon>
<ListItemText primary="home" />
</StyledMenuItem>
</StyledMenu>
</div>
);
}
to use the withStyles
higher-order component to style the menu.
To style the menu items, we can style it with the withStyles
higher-order component.
We set the color with one from the theme
parameter.
Then we can use them all in our App
component.
Max Height Menus
We can set the height of the Menu
with the style
property.
For example, we can write:
import React from "react";
import Button from "@material-ui/core/Button";
import Menu from "@material-ui/core/Menu";
import MenuItem from "@material-ui/core/MenuItem";
const options = ["apple", "orange", "grape", "banana", "pear", "mango"];
export default function App() {
const [anchorEl, setAnchorEl] = React.useState(null);
const handleClick = event => {
setAnchorEl(event.currentTarget);
};
const handleClose = () => {
setAnchorEl(null);
};
return (
<div>
<Button variant="contained" color="primary" onClick={handleClick}>
Open Menu
</Button>
<Menu
anchorEl={anchorEl}
keepMounted
open={Boolean(anchorEl)}
onClose={handleClose}
PaperProps={{
style: {
maxHeight: `200px`
}
}}
>
{options.map(option => (
<MenuItem
key={option}
selected={option === "apple"}
onClick={handleClose}
>
{option}
</MenuItem>
))}
</Menu>
</div>
);
}
We set the maxHeight
property in the PaperProps
to set the height of the menu.
Change Transition
We can add transitions when our menu is opening.
It takes a TransitionComponent
prop to let us add the transition we want.
For example, we can write:
import React from "react";
import Button from "@material-ui/core/Button";
import Menu from "@material-ui/core/Menu";
import MenuItem from "@material-ui/core/MenuItem";
import Fade from "@material-ui/core/Fade";
export default function App() {
const [anchorEl, setAnchorEl] = React.useState(null);
const open = Boolean(anchorEl);
const handleClick = event => {
setAnchorEl(event.currentTarget);
};
const handleClose = () => {
setAnchorEl(null);
};
return (
<div>
<Button onClick={handleClick}>Open</Button>
<Menu
anchorEl={anchorEl}
keepMounted
open={open}
onClose={handleClose}
TransitionComponent={Fade}
>
<MenuItem onClick={handleClose}>home</MenuItem>
<MenuItem onClick={handleClose}>profile</MenuItem>
<MenuItem onClick={handleClose}>logout</MenuItem>
</Menu>
</div>
);
}
to add a fade transition when the menu is opening with the TransitionComponent
prop set to Fade
.
Context Menu
To add a context menu, we can listen to the onContextMenu
prop.
Then we can show the context menu where we right-click by setting the mouse coordinates in the anchorPosition
prop.
For instance, we can write:
import React from "react";
import Menu from "@material-ui/core/Menu";
import MenuItem from "@material-ui/core/MenuItem";
import Typography from "@material-ui/core/Typography";
const initialState = {
mouseX: null,
mouseY: null
};
export default function App() {
const [state, setState] = React.useState(initialState);
const handleClick = event => {
event.preventDefault();
setState({
mouseX: event.clientX - 2,
mouseY: event.clientY - 4
});
};
const handleClose = () => {
setState(initialState);
};
return (
<div onContextMenu={handleClick} 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.
</Typography>
<Menu
keepMounted
open={state.mouseY !== null}
onClose={handleClose}
anchorReference="anchorPosition"
anchorPosition={
state.mouseY !== null && state.mouseX !== null
? { top: state.mouseY, left: state.mouseX }
: undefined
}
>
<MenuItem onClick={handleClose}>select</MenuItem>
<MenuItem onClick={handleClose}>paste</MenuItem>
<MenuItem onClick={handleClose}>copy</MenuItem>
<MenuItem onClick={handleClose}>save</MenuItem>
</Menu>
</div>
);
}
to add a div with some text.
And we add a context menu with the Menu
component.
We add keepMounted
to keep it in the DOM.
open
is true
when mouseY
isn’t null
.
It’s set when we right-click within the handleClick
function.
anchorPosition
lets us set the mousex
and mouseY
to make the menu open with the given mouse coordinates.
Conclusion
We can add menus with styles.
Also, we can add context menus.
Transitions can also be added to change effects when the menu opens.