saleor-dashboard/src/components/SideBar/MenuItem.tsx

185 lines
4.8 KiB
TypeScript
Raw Normal View History

2020-09-07 11:28:59 +00:00
import ClickAwayListener from "@material-ui/core/ClickAwayListener";
import Paper from "@material-ui/core/Paper";
import Popper from "@material-ui/core/Popper";
2020-09-08 09:43:05 +00:00
import { fade } from "@material-ui/core/styles/colorManipulator";
2020-09-07 11:28:59 +00:00
import makeStyles from "@material-ui/core/styles/makeStyles";
2020-09-07 14:34:13 +00:00
import Typography from "@material-ui/core/Typography";
import classNames from "classnames";
2020-09-07 11:28:59 +00:00
import React from "react";
2020-09-07 14:34:13 +00:00
import SVG from "react-inlinesvg";
2020-09-07 11:28:59 +00:00
import { IMenuItem } from "../AppLayout/menuStructure";
export interface MenuItemProps {
2020-09-07 14:34:13 +00:00
active: boolean;
isMenuShrunk: boolean;
2020-09-07 11:28:59 +00:00
menuItem: IMenuItem;
onClick: (url: string, event: React.MouseEvent) => void;
}
2020-09-08 09:43:05 +00:00
export const menuWidth = 210;
export const shrunkMenuWidth = 72;
2020-09-07 11:28:59 +00:00
const useStyles = makeStyles(
theme => ({
2020-09-07 14:34:13 +00:00
hideLabel: {
"&$label": {
opacity: 0
}
},
icon: {
"& svg": {
height: 24,
width: 24
},
marginRight: theme.spacing(1.5),
transition: theme.transitions.duration.shortest + "ms"
},
label: {
cursor: "pointer",
2020-09-07 15:36:55 +00:00
display: "block",
2020-09-07 14:34:13 +00:00
fontSize: 16,
fontWeight: "bold",
opacity: 1,
transition: theme.transitions.duration.shortest + "ms"
},
2020-09-07 11:28:59 +00:00
paper: {
borderRadius: 16,
2020-09-07 14:34:13 +00:00
cursor: "default",
2020-09-07 15:36:55 +00:00
padding: theme.spacing(3),
textAlign: "left"
2020-09-07 11:28:59 +00:00
},
popper: {
marginLeft: theme.spacing(3),
zIndex: 2
2020-09-07 14:34:13 +00:00
},
root: {
2020-09-07 15:36:55 +00:00
"&:hover, &:focus": {
color: theme.palette.primary.main,
outline: 0
2020-09-07 14:34:13 +00:00
},
2020-09-07 15:36:55 +00:00
background: "none",
border: "none",
2020-09-07 14:34:13 +00:00
borderBottomRightRadius: 100,
borderTopRightRadius: 100,
2020-09-08 09:43:05 +00:00
color: fade(theme.palette.text.primary, 0.6),
2020-09-07 14:34:13 +00:00
cursor: "pointer",
display: "flex",
height: 56,
marginBottom: theme.spacing(),
overflow: "hidden",
2020-09-07 15:13:31 +00:00
padding: theme.spacing(2, 3, 2, 3.5),
2020-09-07 14:34:13 +00:00
transition: theme.transitions.duration.shortest + "ms",
2020-09-08 09:43:05 +00:00
width: shrunkMenuWidth
2020-09-07 14:34:13 +00:00
},
rootActive: {
"&$root": {
background: theme.palette.background.paper,
boxShadow: `9px 9px 20px 0 ${theme.palette.grey[300]}`,
color: theme.palette.primary.main
}
},
rootExpanded: {
2020-09-08 09:43:05 +00:00
width: menuWidth
2020-09-07 14:34:13 +00:00
},
subMenuLabel: {
"&$label": {
"&:not(:last-child)": {
marginBottom: theme.spacing(2)
}
},
2020-09-07 15:36:55 +00:00
"&:hover, &:focus": {
2020-09-07 14:34:13 +00:00
color: theme.palette.primary.main
2020-09-07 15:36:55 +00:00
},
background: "none",
2020-09-07 15:58:29 +00:00
border: "none",
2020-09-08 09:43:05 +00:00
color: fade(theme.palette.text.primary, 0.6)
2020-09-07 11:28:59 +00:00
}
}),
{
name: "MenuItem"
}
);
2020-09-07 14:34:13 +00:00
const MenuItem: React.FC<MenuItemProps> = ({
active,
menuItem,
isMenuShrunk,
onClick
}) => {
2020-09-07 11:28:59 +00:00
const classes = useStyles({});
const [open, setOpen] = React.useState(false);
2020-09-07 15:36:55 +00:00
const anchor = React.useRef<HTMLButtonElement>(null);
2020-09-07 11:28:59 +00:00
const handleClick = (event: React.MouseEvent, menuItem: IMenuItem) => {
if (menuItem.children) {
setOpen(true);
} else {
onClick(menuItem.url, event);
setOpen(false);
}
};
return (
2020-09-07 15:36:55 +00:00
<button
2020-09-07 14:34:13 +00:00
className={classNames(classes.root, {
[classes.rootActive]: active,
[classes.rootExpanded]: !isMenuShrunk
})}
ref={anchor}
onClick={event => handleClick(event, menuItem)}
>
{menuItem.icon && <SVG className={classes.icon} src={menuItem.icon} />}
<Typography
2020-09-07 15:36:55 +00:00
aria-label={menuItem.ariaLabel}
2020-09-07 14:34:13 +00:00
className={classNames(classes.label, {
[classes.hideLabel]: isMenuShrunk
})}
variant="body2"
data-test="menu-item-label"
data-test-id={menuItem.testingContextId}
>
{menuItem.label}
</Typography>
2020-09-07 11:28:59 +00:00
{menuItem.children && (
<Popper
className={classes.popper}
open={open}
anchorEl={anchor.current}
transition
disablePortal
placement="right-start"
>
<ClickAwayListener
onClickAway={() => setOpen(false)}
mouseEvent="onClick"
>
<Paper elevation={6} className={classes.paper}>
{menuItem.children.map(subMenuItem => (
2020-09-07 14:34:13 +00:00
<Typography
2020-09-07 15:36:55 +00:00
aria-label={subMenuItem.ariaLabel}
component="button"
2020-09-07 14:34:13 +00:00
className={classNames(classes.label, classes.subMenuLabel)}
2020-09-07 11:28:59 +00:00
key={subMenuItem.url}
2020-09-07 15:36:55 +00:00
onClick={event => {
event.preventDefault();
handleClick(event, subMenuItem);
}}
2020-09-07 14:34:13 +00:00
data-test="submenu-item-label"
data-test-id={subMenuItem.testingContextId}
variant="body2"
2020-09-07 11:28:59 +00:00
>
{subMenuItem.label}
2020-09-07 14:34:13 +00:00
</Typography>
2020-09-07 11:28:59 +00:00
))}
</Paper>
</ClickAwayListener>
</Popper>
)}
2020-09-07 15:36:55 +00:00
</button>
2020-09-07 11:28:59 +00:00
);
};
MenuItem.displayName = "MenuItem";
export default MenuItem;