Skip to content

Feature: Global and App sidebar collapse update #2234

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 21 commits into from
Aug 30, 2023
Merged
Show file tree
Hide file tree
Changes from 11 commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions public/images/githubLogoSmall.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
16 changes: 16 additions & 0 deletions public/images/zestyLogoOnlyGrey.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
115 changes: 115 additions & 0 deletions src/shell/components/AppSidebarButton/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
import { FC, useEffect } from "react";
import { Tooltip, IconButton, SvgIcon, SxProps } from "@mui/material";
import {
KeyboardDoubleArrowLeft,
KeyboardDoubleArrowRight,
} from "@mui/icons-material";
import { useSelector, useDispatch } from "react-redux";
import { useLocation } from "react-router";

import { AppState } from "../../store/types";
import { actions } from "../../store/ui";

interface Props {
inGlobalSidebar?: boolean;
onToggleCollapse?: (collapse: boolean) => void;
}
export const AppSidebarButton: FC<Props> = ({
inGlobalSidebar = false,
onToggleCollapse,
}) => {
const dispatch = useDispatch();
const location = useLocation();
const product = location.pathname.split("/")[1];

const {
contentNavCollapsed,
schemaNavCollapsed,
mediaNavCollapsed,
appsNavCollapsed,
reportsNavCollapsed,
} = useSelector((state: AppState) => state.ui);

const state: Record<string, { collapsed: boolean; toggle: () => void }> = {
content: {
collapsed: contentNavCollapsed,
toggle: () => dispatch(actions.toggleContentNav(!contentNavCollapsed)),
},
schema: {
collapsed: schemaNavCollapsed,
toggle: () => dispatch(actions.toggleSchemaNav(!schemaNavCollapsed)),
},
media: {
collapsed: mediaNavCollapsed,
toggle: () => dispatch(actions.toggleMediaNav(!mediaNavCollapsed)),
},
apps: {
collapsed: appsNavCollapsed,
toggle: () => dispatch(actions.toggleAppsNav(!appsNavCollapsed)),
},
reports: {
collapsed: reportsNavCollapsed,
toggle: () => dispatch(actions.toggleReportsNav(!reportsNavCollapsed)),
},
};

useEffect(() => {
onToggleCollapse && onToggleCollapse(state[product]?.collapsed);
}, [state[product]?.collapsed]);

if (
(inGlobalSidebar && !state[product]?.collapsed) ||
(!inGlobalSidebar && state[product]?.collapsed)
) {
return <></>;
}

return (
<Tooltip
title={state[product]?.collapsed ? "Expand Sidebar" : "Collapse Sidebar"}
placement="right-start"
enterDelay={1000}
enterNextDelay={1000}
>
<IconButton
data-cy="collapseAppSideBar"
onClick={() => state[product]?.toggle()}
sx={{
borderRadius: "50%",
borderColor: "grey.600",
borderStyle: "solid",
borderWidth: "1px",
backgroundColor: "grey.900",

width: "24px",
height: "24px",

position: "absolute",
top: inGlobalSidebar ? "72px" : "32px",
right: "-12px",
zIndex: (theme) => theme.zIndex.appBar,

"&:hover": {
backgroundColor: "grey.900",

".MuiSvgIcon-root": {
color: "common.white",
},
},
}}
>
<SvgIcon
component={
state[product]?.collapsed
? KeyboardDoubleArrowRight
: KeyboardDoubleArrowLeft
}
fontSize="small"
sx={{
color: "grey.500",
}}
/>
</IconButton>
</Tooltip>
);
};
13 changes: 12 additions & 1 deletion src/shell/components/ResizeableContainer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ import React, { useCallback, useEffect, useMemo, useState } from "react";
import { Box } from "@mui/material";
import { useLocalStorage } from "react-use";

import { AppSidebarButton } from "./AppSidebarButton";

type Props = {
children: React.ReactNode;
minWidth: number;
Expand All @@ -17,6 +19,7 @@ export const ResizableContainer = ({
defaultWidth,
id,
}: Props) => {
const [collapsed, setCollapsed] = useState(false);
const [isResizing, setIsResizing] = useState(false);
const [initialPos, setInitialPos] = useState(0);
const [initialWidth, setInitialWidth] = useState(0);
Expand Down Expand Up @@ -66,7 +69,11 @@ export const ResizableContainer = ({
const MemoizedChildren = useMemo(() => children, [children]);

return (
<Box width={width} position="relative">
<Box
width={collapsed ? 0 : width}
position="relative"
overflow={collapsed ? "hidden" : "visible"}
>
{MemoizedChildren}
<Box
sx={{
Expand All @@ -83,6 +90,10 @@ export const ResizableContainer = ({
},
}}
onMouseDown={handleMouseDown}
display={collapsed ? "none" : "block"}
/>
<AppSidebarButton
onToggleCollapse={(collapsed) => setCollapsed(collapsed)}
/>
</Box>
);
Expand Down
142 changes: 66 additions & 76 deletions src/shell/components/global-sidebar/GlobalSidebar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,19 +9,20 @@ import {
Avatar,
Stack,
Link,
Tooltip,
ListItem,
} from "@mui/material";
import GroupAddIcon from "@mui/icons-material/GroupAdd";
import MenuBookIcon from "@mui/icons-material/MenuBook";
import KeyboardDoubleArrowLeftIcon from "@mui/icons-material/KeyboardDoubleArrowLeft";
import KeyboardDoubleArrowRightIcon from "@mui/icons-material/KeyboardDoubleArrowRight";
import ArrowDropDownIcon from "@mui/icons-material/ArrowDropDown";
import ArrowDropDownRoundedIcon from "@mui/icons-material/ArrowDropDownRounded";
import MenuRoundedIcon from "@mui/icons-material/MenuRounded";
import { theme } from "@zesty-io/material";

import GlobalMenu from "../global-menu";
import Favicon from "../favicon";
import zestyLogo from "../../../../public/images/zestyLogo.svg";
import zestyLogoOnly from "../../../../public/images/zestyLogoOnly.svg";
import zestyLogoOnlyGrey from "../../../../public/images/zestyLogoOnlyGrey.svg";
import githubLogoSmall from "../../../../public/images/githubLogoSmall.svg";
import InviteMembersModal from "../InviteMembersModal";
import { User } from "../../services/types";
import { useGetInstanceQuery } from "../../services/accounts";
Expand All @@ -31,6 +32,7 @@ import { actions } from "../../store/ui";
import { OnboardingCall } from "./components/OnboardingCall";
import { GlobalAccountMenu } from "../GlobalAccountMenu";
import { GlobalDocsMenu } from "../GlobalDocsMenu";
import { AppSidebarButton } from "../AppSidebarButton";

interface GlobalSidebarProps {
openNav: boolean;
Expand Down Expand Up @@ -62,84 +64,72 @@ const GlobalSidebar: FC<GlobalSidebarProps> = ({ onClick, openNav }) => {
borderColor: "grey.800",
}}
>
<InstanceMenu openNav={openNav} />

{/* Sidebar handle */}
<Tooltip
title={openNav ? "Collapse Sidebar" : "Expand Sidebar"}
placement="right-start"
enterDelay={1000}
enterNextDelay={1000}
<ListItem
sx={{
height: 36,
px: 1.5,
py: 0.75,
mt: 0.75,
display: "flex",
alignItems: "center",
justifyContent: "space-between",
}}
>
<IconButton
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We want to keep this as a button for accessibility reasons. At the very least we need to give it role="button" and make sure it can be tabbed focused into

<MenuRoundedIcon
data-cy="CollapseGlobalSideBar"
onClick={onClick}
sx={{
borderRadius: "50%",
borderColor: "grey.600",
borderStyle: "solid",
borderWidth: "1px",
backgroundColor: "grey.900",

width: "24px",
height: "24px",
sx={{ color: "grey.400", cursor: "pointer" }}
/>
{openNav && (
<Box
component="img"
src={zestyLogoOnlyGrey}
alt="Zesty Logo"
width={20}
height={20}
/>
)}
</ListItem>

position: "absolute",
top: "32px",
right: "-14px",
zIndex: (theme) => theme.zIndex.appBar,
<InstanceMenu openNav={openNav} />

"&:hover": {
backgroundColor: "grey.900",

".MuiSvgIcon-root": {
color: "common.white",
},
},
}}
>
{openNav ? (
<KeyboardDoubleArrowLeftIcon
fontSize="small"
sx={{
color: "grey.500",
}}
/>
) : (
<KeyboardDoubleArrowRightIcon
fontSize="small"
sx={{ color: "grey.500" }}
/>
)}
</IconButton>
</Tooltip>
<AppSidebarButton inGlobalSidebar />

<GlobalMenu />
{is15DaysFromCreation && openNav && <OnboardingCall />}

{/* Bottom bar */}
<Box position="absolute" bottom={0} left={0} right={0}>
{is15DaysFromCreation && openNav && <OnboardingCall />}

{!is15DaysFromCreation && (
<Stack
direction={openNav ? "row" : "column"}
alignItems="center"
height={openNav ? 24 : "inherit"}
px={2.5}
mb={openNav ? 1.25 : 0}
pt={openNav ? 0 : 1.5}
gap={1.5}
borderTop={openNav ? "none" : "1px solid"}
sx={{
borderColor: "grey.800",
}}
>
<img
src={openNav ? zestyLogo : zestyLogoOnly}
alt="Zesty Logo"
width={openNav ? 84 : 20}
height={openNav ? 24 : 20}
/>
<Stack
direction={openNav ? "row" : "column"}
alignItems="center"
justifyContent="space-between"
height={openNav ? 24 : "inherit"}
px={1.5}
mb={openNav ? 1.5 : 0}
pt={openNav ? 0 : 1.5}
gap={1.5}
borderTop={openNav ? "none" : "1px solid"}
sx={{
borderColor: "grey.800",
}}
>
<img
src={openNav ? zestyLogo : zestyLogoOnly}
alt="Zesty Logo"
width={openNav ? 84 : 20}
height={openNav ? 24 : 20}
/>
<Stack direction="row" gap={0.5} alignItems="end">
{openNav && (
<Box
component="img"
src={githubLogoSmall}
alt="Github Logo"
width={12}
height={12}
/>
)}
<Link
fontFamily="Roboto Mono"
fontSize={10}
Expand All @@ -165,7 +155,7 @@ const GlobalSidebar: FC<GlobalSidebarProps> = ({ onClick, openNav }) => {
}
</Link>
</Stack>
)}
</Stack>

<Stack
width="inherit"
Expand All @@ -175,7 +165,7 @@ const GlobalSidebar: FC<GlobalSidebarProps> = ({ onClick, openNav }) => {
alignItems="center"
flexDirection={openNav ? "row" : "column-reverse"}
py={1.25}
px={2.5}
px={openNav ? 1.5 : 1}
gap={openNav ? 0 : 1}
sx={{
borderColor: "grey.800",
Expand Down Expand Up @@ -206,8 +196,8 @@ const GlobalSidebar: FC<GlobalSidebarProps> = ({ onClick, openNav }) => {
}}
/>
{openNav && (
<ArrowDropDownIcon
fontSize="inherit"
<ArrowDropDownRoundedIcon
fontSize="small"
sx={{
color: "grey.500",
}}
Expand Down
Loading