Skip to content

Commit

Permalink
feat: add recursive nested menu
Browse files Browse the repository at this point in the history
  • Loading branch information
santospatrick committed Aug 2, 2022
1 parent fa4256b commit 27f0676
Show file tree
Hide file tree
Showing 4 changed files with 102 additions and 33 deletions.
35 changes: 3 additions & 32 deletions src/components/MainDrawer/MainDrawer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,27 +9,24 @@ import {
DrawerProps,
HStack,
IconButton,
List,
ListItem,
Stack,
Link,
} from "@chakra-ui/react";
import Image from "next/image";
import React, { useContext, useEffect, useState } from "react";
import React, { useContext, useEffect } from "react";
import { MdMenu } from "react-icons/md";
import logo from "@/assets/logo.svg";
import NextLink from "next/link";
import { AuthContext } from "@/contexts/AuthContext";
import { useRouter } from "next/router";
import MenuLink from "./MenuLink";
import { menu } from "./menu";
import SideMenu from "./SideMenu";

type Props = Pick<DrawerProps, "onClose" | "isOpen">;

function MainDrawer({ onClose, isOpen }: Props) {
const { user, logout } = useContext(AuthContext);
const router = useRouter();
const [nestedMenuOpen, setNestedMenuOpen] = useState<number | null>(null);

useEffect(() => {
onClose();
Expand Down Expand Up @@ -57,33 +54,7 @@ function MainDrawer({ onClose, isOpen }: Props) {
</Stack>
</DrawerHeader>
<DrawerBody display="flex" flexDirection="column" p={0}>
<List onClick={onClose}>
{menu.map((menuItem, menuItemKey) => (
<ListItem display="flex" flexDirection="column" key={menuItemKey}>
<MenuLink
isOpened={nestedMenuOpen === menuItemKey}
onClickDropdown={() => {
if (nestedMenuOpen === menuItemKey) {
setNestedMenuOpen(null);
} else {
setNestedMenuOpen(menuItemKey);
}
}}
{...menuItem}
/>
{nestedMenuOpen === menuItemKey && (
<List pl={6}>
{menuItem.children &&
menuItem.children.map((child, childIndex) => (
<ListItem display="flex" key={childIndex}>
<MenuLink {...child} />
</ListItem>
))}
</List>
)}
</ListItem>
))}
</List>
<SideMenu items={menu} />
<Box
onClick={onClose}
display="flex"
Expand Down
86 changes: 86 additions & 0 deletions src/components/MainDrawer/SideMenu.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
import React, { useState } from "react";
import { Box, Button, ListIcon, ListItem, Text } from "@chakra-ui/react";
import NextLink from "next/link";
import * as Styled from "./styles";
import { MdArrowDropDown, MdArrowRight } from "react-icons/md";
import { useRouter } from "next/router";

type Props = {
items: any[];
};

const SideMenu = ({ items }: Props) => {
const [displayChildren, setDisplayChildren] = useState<
Record<string, boolean>
>({});
const router = useRouter();

return (
<Styled.NestedList>
{items.map((item) => (
<ListItem display="flex" flexDirection="column" key={item.text}>
{item.children ? (
<Button
onClick={() => {
setDisplayChildren((prevState) => ({
...prevState,
[item.text]: !displayChildren[item.text],
}));
}}
p={0}
variant="ghost"
borderRadius={0}
>
<Box
display="flex"
alignItems="center"
height="48px"
p={3}
width="100%"
>
<ListIcon fontSize="24px" as={item.icon} color="gray.500" />
<Text fontWeight="normal">{item.text}</Text>
<ListIcon
ml="auto"
fontSize="24px"
as={
displayChildren[item.text] ? MdArrowDropDown : MdArrowRight
}
color="gray.500"
/>
</Box>
</Button>
) : (
<NextLink href={item.href} passHref>
<Box
color={item.href === router.pathname ? "brand.500" : undefined}
display="flex"
alignItems="center"
height="48px"
as="a"
p={3}
width="100%"
>
{item.icon && (
<ListIcon
fontSize="24px"
as={item.icon}
color={
item.href === router.pathname ? "brand.500" : "gray.500"
}
/>
)}
<span>{item.text}</span>
</Box>
</NextLink>
)}
{displayChildren[item.text] && item.children && (
<SideMenu items={item.children} />
)}
</ListItem>
))}
</Styled.NestedList>
);
};

export default SideMenu;
12 changes: 12 additions & 0 deletions src/components/MainDrawer/styles.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { List, Theme } from "@chakra-ui/react";
import styled from "@emotion/styled";

export const NestedList = styled(List)<{ theme?: Theme }>`
ul {
padding-left: ${({ theme }) => theme.space[3]};
}
a {
height: 40px;
}
`;
2 changes: 1 addition & 1 deletion src/config/theme.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ export const override = {
colors: {
brand: {
50: "#e7f6fd", // hover
500: "#478ad2", // button background color
500: "#478ad2", // button background color, menu link color
600: "#2a69ac", // active
},
},
Expand Down

0 comments on commit 27f0676

Please sign in to comment.