orchetera
Version:
Welcome to **Orchetera** — your orchestration tool to kickstart Firebase-ready projects with ease!
177 lines (161 loc) • 4.45 kB
JSX
import { useEffect, useState } from "react";
import {
List,
ListItem,
ListItemButton,
ListItemIcon,
ListItemText,
Collapse,
Paper,
Popper,
Divider,
} from "@mui/material";
import { useTheme } from "@mui/material/styles";
import { ExpandLess, ExpandMore } from "@mui/icons-material";
const MultiLevelMenu = ({ menuData, open }) => {
return (
<List component="nav" sx={{ width: 250 }}>
{menuData.map((menuItem, index) => (
<MenuItem sidebarOpen={open} key={index} item={menuItem} level={1} />
))}
</List>
);
};
const MenuItem = ({ item, level, sidebarOpen }) => {
const theme = useTheme();
const [open, setOpen] = useState(false);
const [anchorEl, setAnchorEl] = useState(null);
const [popoverOpen, setPopoverOpen] = useState(false);
const [popoverHovered, setPopoverHovered] = useState(true);
const hasChildren = item.children && item.children.length > 0;
const isPopoverLevel = level >= 3;
const handleClick = () => {
console.log("sidebarOpen", sidebarOpen);
if (!sidebarOpen) return;
if (isPopoverLevel) return;
setOpen(!open);
};
const handleMouseEnter = (event) => {
if (!sidebarOpen) return;
if (isPopoverLevel) {
setAnchorEl(event.currentTarget);
setPopoverOpen(true);
}
};
const handleMouseLeave = () => {
if (!sidebarOpen) return;
if (isPopoverLevel && !popoverHovered) {
setPopoverOpen(false);
}
};
const handlePopoverEnter = () => {
if (!sidebarOpen) return;
setPopoverHovered(true);
};
const handlePopoverLeave = () => {
if (!sidebarOpen) return;
setPopoverHovered(false);
setPopoverOpen(false);
};
useEffect(() => {
if (!sidebarOpen) {
setOpen(false);
setPopoverHovered(false);
setPopoverOpen(false);
}
console.log("sidebarUseeffect", sidebarOpen);
}, [sidebarOpen]);
return (
<>
<ListItem
disablePadding
onMouseEnter={handleMouseEnter}
onMouseLeave={handleMouseLeave}
sx={{ display: "block" }}
>
<ListItemButton
onClick={handleClick}
sx={{
// pl: level * 2,
minHeight: 48,
justifyContent: "initial",
px: 2.5,
"&:hover": {
backgroundColor: "action.hover",
},
}}
// selected={true}
>
{item.icon && (
<ListItemIcon
sx={{
color: theme.palette.primary.contrastText,
minWidth: 0,
mr: 3,
justifyContent: "center",
}}
>
{item.icon}
</ListItemIcon>
)}
<ListItemText primary={item.name} sx={{ opacity: 1 }} />
{hasChildren &&
!isPopoverLevel &&
(open ? <ExpandLess /> : <ExpandMore />)}
</ListItemButton>
</ListItem>
{hasChildren && !isPopoverLevel && (
<Collapse in={open} timeout="auto" unmountOnExit>
<List component="div" disablePadding>
{item.children.map((child, idx) => (
<MenuItem
sidebarOpen={open}
key={idx}
item={child}
level={level + 1}
/>
))}
</List>
</Collapse>
)}
{hasChildren && isPopoverLevel && (
<Popper
open={popoverOpen}
onMouseEnter={handlePopoverEnter}
onMouseLeave={handlePopoverLeave}
anchorEl={anchorEl}
placement={level % 2 === 0 ? "right-start" : "right-end"}
modifiers={[
{
name: "offset",
options: {
offset: [0, 0],
},
},
]}
sx={{
zIndex: 1300,
marginLeft: "-10px !important",
"&.MuiPopper-root": {
marginLeft: "-10px !important",
},
}}
>
<Paper elevation={3} sx={{ minWidth: 200 }}>
<List>
{item.children.map((child, idx) => (
<MenuItem
sidebarOpen={open}
key={idx}
item={child}
level={level + 1}
/>
))}
</List>
</Paper>
</Popper>
)}
</>
);
};
export default MultiLevelMenu;