From bf752d1ee7f66b74fb888aeeeceb5c62c32cbcce Mon Sep 17 00:00:00 2001 From: dominik-zeglen Date: Fri, 11 Sep 2020 15:58:15 +0200 Subject: [PATCH] Add mobile drawer menu --- src/components/AppLayout/AppLayout.tsx | 11 +- src/components/SideBar/SideBar.tsx | 19 +-- src/components/SideBarDrawer/MenuItemBtn.tsx | 32 +++++ .../SideBarDrawer/SideBarDrawer.stories.tsx | 37 +++++ .../SideBarDrawer/SideBarDrawer.tsx | 132 ++++++++++++++++++ src/components/SideBarDrawer/index.ts | 0 src/components/SideBarDrawer/styles.ts | 68 +++++++++ 7 files changed, 290 insertions(+), 9 deletions(-) create mode 100644 src/components/SideBarDrawer/MenuItemBtn.tsx create mode 100644 src/components/SideBarDrawer/SideBarDrawer.stories.tsx create mode 100644 src/components/SideBarDrawer/SideBarDrawer.tsx create mode 100644 src/components/SideBarDrawer/index.ts create mode 100644 src/components/SideBarDrawer/styles.ts diff --git a/src/components/AppLayout/AppLayout.tsx b/src/components/AppLayout/AppLayout.tsx index 1d275c8b3..891ef3f09 100644 --- a/src/components/AppLayout/AppLayout.tsx +++ b/src/components/AppLayout/AppLayout.tsx @@ -16,6 +16,7 @@ import ErrorPage from "../ErrorPage"; import Navigator from "../Navigator"; import NavigatorButton from "../NavigatorButton/NavigatorButton"; import SideBar from "../SideBar"; +import SideBarDrawer from "../SideBarDrawer/SideBarDrawer"; import UserChip from "../UserChip"; import AppActionContext from "./AppActionContext"; import AppHeaderContext from "./AppHeaderContext"; @@ -162,7 +163,15 @@ const AppLayout: React.FC = ({ children }) => {
{isMdUp &&
} - {!isMdUp && <>=} + {!isMdUp && ( + + )}
({ + ariaLabel: "configure", + icon: configurationIcon, + label: intl.formatMessage(sectionNames.configuration), + testingContextId: "configure", + url: configurationMenuUrl +}); + const SideBar: React.FC = ({ location, menuItems, @@ -65,6 +73,7 @@ const SideBar: React.FC = ({ const classes = useStyles({}); const [isShrunk, setShrink] = useLocalStorage("isMenuSmall", false); const intl = useIntl(); + const configureMenuItem = getConfigureMenuItem(intl); return (
= ({ ) } isMenuShrunk={isShrunk} - menuItem={{ - ariaLabel: "configure", - icon: configurationIcon, - label: intl.formatMessage(sectionNames.configuration), - testingContextId: "configure", - url: configurationMenuUrl - }} + menuItem={configureMenuItem} onClick={onMenuItemClick} /> )} diff --git a/src/components/SideBarDrawer/MenuItemBtn.tsx b/src/components/SideBarDrawer/MenuItemBtn.tsx new file mode 100644 index 000000000..9013d5f36 --- /dev/null +++ b/src/components/SideBarDrawer/MenuItemBtn.tsx @@ -0,0 +1,32 @@ +import Typography from "@material-ui/core/Typography"; +import { UseNavigatorResult } from "@saleor/hooks/useNavigator"; +import React from "react"; +import SVG from "react-inlinesvg"; + +import { IMenuItem } from "../AppLayout/menuStructure"; +import useStyles from "./styles"; + +export interface MenuItemBtnProps { + menuItem: IMenuItem; + onClick: UseNavigatorResult; +} +const MenuItemBtn: React.FC = ({ menuItem, onClick }) => { + const classes = useStyles({}); + + return ( + + ); +}; + +MenuItemBtn.displayName = "MenuItemBtn"; +export default MenuItemBtn; diff --git a/src/components/SideBarDrawer/SideBarDrawer.stories.tsx b/src/components/SideBarDrawer/SideBarDrawer.stories.tsx new file mode 100644 index 000000000..057ee7b90 --- /dev/null +++ b/src/components/SideBarDrawer/SideBarDrawer.stories.tsx @@ -0,0 +1,37 @@ +import { staffMember } from "@saleor/staff/fixtures"; +import Decorator from "@saleor/storybook/Decorator"; +import { storiesOf } from "@storybook/react"; +import { config } from "@test/intl"; +import React from "react"; +import { createIntl } from "react-intl"; + +import createMenuStructure from "../AppLayout/menuStructure"; +import SideBarDrawer from "./SideBarDrawer"; + +const intl = createIntl(config); +const user = { + __typename: staffMember.__typename, + avatar: { + __typename: staffMember.avatar.__typename, + url: staffMember.avatar.url + }, + email: staffMember.email, + firstName: "Adam Evan", + id: staffMember.id, + isStaff: true, + lastName: "Newton", + note: null, + userPermissions: staffMember.userPermissions +}; + +storiesOf("Generics / Mobile Side Menu", module) + .addDecorator(Decorator) + .add("default", () => ( + undefined} + renderConfigure={true} + user={user} + /> + )); diff --git a/src/components/SideBarDrawer/SideBarDrawer.tsx b/src/components/SideBarDrawer/SideBarDrawer.tsx new file mode 100644 index 000000000..e7963401c --- /dev/null +++ b/src/components/SideBarDrawer/SideBarDrawer.tsx @@ -0,0 +1,132 @@ +import logoLight from "@assets/images/logo-sidebar-light.svg"; +import { Typography } from "@material-ui/core"; +import Drawer from "@material-ui/core/Drawer"; +import ArrowLeftIcon from "@material-ui/icons/ArrowLeft"; +import MenuIcon from "@material-ui/icons/Menu"; +import classNames from "classnames"; +import React from "react"; +import SVG from "react-inlinesvg"; +import { useIntl } from "react-intl"; + +import { IMenuItem } from "../AppLayout/menuStructure"; +import { getConfigureMenuItem, SideBarProps } from "../SideBar/SideBar"; +import SquareButton from "../SquareButton"; +import MenuItemBtn from "./MenuItemBtn"; +import useStyles from "./styles"; + +export type SideBarDrawerProps = SideBarProps; + +const SideBarDrawer: React.FC = ({ + menuItems, + onMenuItemClick, + renderConfigure, + user +}) => { + const [isOpened, setOpened] = React.useState(false); + const classes = useStyles({}); + const intl = useIntl(); + const [activeMenu, setActiveMenu] = React.useState(null); + const [showSubmenu, setShowSubmenu] = React.useState(false); + const container = React.useRef(null); + + const configureMenuItem = getConfigureMenuItem(intl); + + const handleMenuItemClick = (url: string) => { + setOpened(false); + setShowSubmenu(false); + onMenuItemClick(url); + }; + + const handleMenuItemWithChildrenClick = (menuItem: IMenuItem) => { + setActiveMenu(menuItem); + setShowSubmenu(true); + container.current.scrollTo({ + top: 0 + }); + }; + + return ( + <> + setOpened(true)}> + + + setOpened(false)} + > +
+
+
+ + {menuItems.map(menuItem => { + if ( + menuItem.permission && + !user.userPermissions + .map(perm => perm.code) + .includes(menuItem.permission) + ) { + return null; + } + + return ( + handleMenuItemWithChildrenClick(menuItem) + : handleMenuItemClick + } + key={menuItem.ariaLabel} + /> + ); + })} + {renderConfigure && ( + + )} +
+ {activeMenu && ( +
+
+
+ + + {activeMenu.label} + +
+ setShowSubmenu(false)}> + + +
+ {activeMenu.children.map(subMenuItem => ( + + ))} +
+ )} +
+
+
+ + ); +}; + +SideBarDrawer.displayName = "SideBarDrawer"; +export default SideBarDrawer; diff --git a/src/components/SideBarDrawer/index.ts b/src/components/SideBarDrawer/index.ts new file mode 100644 index 000000000..e69de29bb diff --git a/src/components/SideBarDrawer/styles.ts b/src/components/SideBarDrawer/styles.ts new file mode 100644 index 000000000..92cda2a00 --- /dev/null +++ b/src/components/SideBarDrawer/styles.ts @@ -0,0 +1,68 @@ +import makeStyles from "@material-ui/core/styles/makeStyles"; + +const useStyles = makeStyles( + theme => ({ + activeMenuLabel: { + display: "flex" + }, + container: { + overflowX: "hidden", + width: "100%" + }, + containerSubMenu: { + "&$container": { + overflow: "hidden" + } + }, + content: { + width: "50%" + }, + icon: { + marginRight: theme.spacing(2) + }, + innerContainer: { + display: "flex", + position: "relative", + right: 0, + transition: theme.transitions.duration.short + "ms", + width: "200%" + }, + label: { + fontWeight: "bold" + }, + logo: { + display: "block", + marginBottom: theme.spacing(4) + }, + menuItemBtn: { + alignItems: "center", + background: "none", + border: "none", + color: theme.palette.text.secondary, + display: "flex", + marginBottom: theme.spacing(3), + padding: 0 + }, + root: { + background: theme.palette.background.default, + borderBottomRightRadius: 32, + borderTopRightRadius: 32, + padding: theme.spacing(3), + width: 260 + }, + secondaryContentActive: { + right: "100%" + }, + subMenuTopBar: { + alignItems: "center", + display: "flex", + justifyContent: "space-between", + marginBottom: theme.spacing(3) + } + }), + { + name: "SideBarDrawer" + } +); + +export default useStyles;