Skip to content

Commit

Permalink
Adaptive navigation drawer
Browse files Browse the repository at this point in the history
  • Loading branch information
pkirilin committed Mar 29, 2024
1 parent 9daf166 commit 66e14c8
Show file tree
Hide file tree
Showing 4 changed files with 89 additions and 46 deletions.
4 changes: 3 additions & 1 deletion src/frontend/src/shared/constants.ts
Original file line number Diff line number Diff line change
@@ -1 +1,3 @@
export const APP_BAR_HEIGHT = 75;
export const APP_BAR_HEIGHT = 66;

export const SIDEBAR_DRAWER_WIDTH = 256;
34 changes: 23 additions & 11 deletions src/frontend/src/shared/ui/AppShell.tsx
Original file line number Diff line number Diff line change
@@ -1,41 +1,53 @@
import { AppBar, Container, LinearProgress } from '@mui/material';
import { AppBar, Box, Container, LinearProgress, Toolbar } from '@mui/material';
import { type PropsWithChildren, type FC, type ReactElement } from 'react';
import { APP_BAR_HEIGHT, SIDEBAR_DRAWER_WIDTH } from '../constants';

interface Props extends PropsWithChildren {
withNavigationProgress: boolean;
withAdditionalNavigation?: boolean;
withSidebar?: boolean;
header?: ReactElement;
}

export const AppShell: FC<Props> = ({
children,
withNavigationProgress,
withAdditionalNavigation,
withSidebar,
header,
}) => (
<>
{header && (
<AppBar position="sticky">
<Container>{header}</Container>
<AppBar variant="outlined">
<Box component={Toolbar} disableGutters px={{ xs: 1, sm: 2, md: 1 }}>
{header}
</Box>
</AppBar>
)}
{withNavigationProgress && (
<LinearProgress
sx={{
position: 'absolute',
top: 0,
top: APP_BAR_HEIGHT,
width: '100%',
}}
/>
)}
<Container
<Box
component="main"
sx={theme => ({
paddingTop: withAdditionalNavigation ? 0 : theme.spacing(3),
paddingBottom: theme.spacing(3),
})}
pt={withAdditionalNavigation ? 0 : 3}
pb={3}
ml={{
xs: 0,
md: withSidebar ? `${SIDEBAR_DRAWER_WIDTH}px` : 0,
}}
width={{
xs: '100%',
md: withSidebar ? `calc(100% - ${SIDEBAR_DRAWER_WIDTH}px)` : '100%',
}}
>
{children}
</Container>
{header && <Toolbar />}
<Container>{children}</Container>
</Box>
</>
);
7 changes: 6 additions & 1 deletion src/frontend/src/widgets/layout/ui/PrivateLayout.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import { type Theme, useMediaQuery } from '@mui/material';
import { type PropsWithChildren, type FC, type ReactElement } from 'react';
import { useAuthStatusCheckEffect } from '@/features/auth';
import { useToggle } from '@/shared/hooks';
import { AppShell } from '@/shared/ui';
import { NavigationBar } from '@/widgets/navbar';
import { useNavigationProgress } from '../lib';
Expand All @@ -11,16 +13,19 @@ interface Props extends PropsWithChildren {

export const PrivateLayout: FC<Props> = ({ children, header, withAdditionalNavigation }) => {
const navigationProgressVisible = useNavigationProgress();
const isMobile = useMediaQuery<Theme>(theme => theme.breakpoints.down('md'));
const [menuOpened, toggleMenu] = useToggle(!isMobile);

useAuthStatusCheckEffect();

return (
<AppShell
withNavigationProgress={navigationProgressVisible}
withAdditionalNavigation={withAdditionalNavigation}
withSidebar={menuOpened}
header={
<>
<NavigationBar />
<NavigationBar menuOpened={menuOpened} toggleMenu={toggleMenu} />
{header}
</>
}
Expand Down
90 changes: 57 additions & 33 deletions src/frontend/src/widgets/navbar/ui/NavigationBar.tsx
Original file line number Diff line number Diff line change
@@ -1,53 +1,77 @@
import CloseIcon from '@mui/icons-material/Close';
import LogoutIcon from '@mui/icons-material/Logout';
import MenuIcon from '@mui/icons-material/Menu';
import { AppBar, Box, Drawer, IconButton, Toolbar, Tooltip, Typography } from '@mui/material';
import {
AppBar,
Box,
Drawer,
IconButton,
type Theme,
Toolbar,
Tooltip,
Typography,
useMediaQuery,
} from '@mui/material';
import { type FC } from 'react';
import { Form } from 'react-router-dom';
import { useToggle } from '@/shared/hooks';
import { APP_BAR_HEIGHT, SIDEBAR_DRAWER_WIDTH } from '@/shared/constants';
import { APP_NAME } from '../lib';
import { MenuList } from './MenuList';

export const NavigationBar: FC = () => {
const [menuOpened, toggleMenu] = useToggle();
interface Props {
menuOpened: boolean;
toggleMenu: () => void;
}

export const NavigationBar: FC<Props> = ({ menuOpened, toggleMenu }) => {
const isMobile = useMediaQuery<Theme>(theme => theme.breakpoints.down('md'));

return (
<Box
component={Toolbar}
disableGutters
display="flex"
justifyContent="space-between"
alignItems="center"
gap={1}
flex={1}
width="100%"
>
<Box display="flex" gap={1} alignItems="center">
<IconButton edge="start" color="inherit" aria-label="Open menu" onClick={toggleMenu}>
<MenuIcon />
</IconButton>
<Typography variant="h6" component="div">
{APP_NAME}
</Typography>
</Box>
<Box component={Form} method="post" action="/logout">
<Tooltip title="Logout">
<IconButton type="submit" edge="end" aria-label="Logout">
<LogoutIcon sx={theme => ({ fill: theme.palette.primary.contrastText })} />
<>
<Box
display="flex"
justifyContent="space-between"
alignItems="center"
gap={1}
flex={1}
width="100%"
>
<Box display="flex" gap={{ xs: 1, md: 3 }} alignItems="center">
<IconButton color="inherit" aria-label="Open menu" onClick={toggleMenu}>
<MenuIcon />
</IconButton>
</Tooltip>
<Typography variant="h6" component="div">
{APP_NAME}
</Typography>
</Box>
<Box component={Form} method="post" action="/logout">
<Tooltip title="Logout">
<IconButton type="submit" aria-label="Logout">
<LogoutIcon sx={theme => ({ fill: theme.palette.primary.contrastText })} />
</IconButton>
</Tooltip>
</Box>
</Box>
<Drawer
variant={isMobile ? 'temporary' : 'persistent'}
open={menuOpened}
onClose={toggleMenu}
ModalProps={{ keepMounted: true }}
ModalProps={{ keepMounted: isMobile }}
PaperProps={{
sx: { width: '75%' },
sx: {
marginTop: { xs: 0, md: `${APP_BAR_HEIGHT}px` },
width: { xs: '75%', md: `${SIDEBAR_DRAWER_WIDTH}px` },
},
component: 'nav',
}}
>
<AppBar position="static">
<Box p={1} component={Toolbar} disableGutters>
<Box
component={AppBar}
variant="outlined"
position="static"
display={{ xs: 'block', md: 'none' }}
>
<Box px={1} component={Toolbar} disableGutters>
<Box display="flex" gap={3} alignItems="center">
<IconButton color="inherit" aria-label="Close menu" onClick={toggleMenu}>
<CloseIcon />
Expand All @@ -57,9 +81,9 @@ export const NavigationBar: FC = () => {
</Typography>
</Box>
</Box>
</AppBar>
</Box>
<MenuList />
</Drawer>
</Box>
</>
);
};

0 comments on commit 66e14c8

Please sign in to comment.