Skip to content

Commit

Permalink
Use separate subheader for PageDetailHeader
Browse files Browse the repository at this point in the history
  • Loading branch information
pkirilin committed Mar 29, 2024
1 parent 66e14c8 commit f6104f6
Show file tree
Hide file tree
Showing 7 changed files with 81 additions and 57 deletions.
38 changes: 11 additions & 27 deletions src/frontend/src/features/pages/ui/PageDetailHeader.tsx
Original file line number Diff line number Diff line change
@@ -1,25 +1,18 @@
import ArrowBackIcon from '@mui/icons-material/ArrowBack';
import {
AppBar,
Box,
Container,
IconButton,
Stack,
Toolbar,
Tooltip,
Typography,
type TypographyProps,
styled,
useScrollTrigger,
} from '@mui/material';
import { useMemo, type FC } from 'react';
import { Link as RouterLink } from 'react-router-dom';
import { notesApi } from 'src/features/notes';
import { formatDate } from 'src/utils';
import { type Page } from '../models';

const DIVIDER_VISIBLE_SCROLL_THRESHOLD = 16;

interface Props {
page: Page;
}
Expand All @@ -35,26 +28,17 @@ export const PageDetailHeader: FC<Props> = ({ page }) => {
const notes = useMemo(() => getNotesQuery.data ?? [], [getNotesQuery.data]);
const totalCalories = useMemo(() => notes.reduce((sum, note) => sum + note.calories, 0), [notes]);

const pageScrolled = useScrollTrigger({
threshold: DIVIDER_VISIBLE_SCROLL_THRESHOLD,
disableHysteresis: true,
});

return (
<AppBar color="inherit" position="static" elevation={pageScrolled ? 1 : 0} component="nav">
<Container>
<Toolbar disableGutters component={Box} display="flex" alignItems="center" gap={2}>
<Tooltip title="Back to pages list">
<IconButton edge="start" component={RouterLink} to="/pages">
<ArrowBackIcon />
</IconButton>
</Tooltip>
<Stack direction="row" spacing={2} justifyContent="space-between" width="100%">
<TextStyled component="h1">{formatDate(new Date(page.date))}</TextStyled>
<TextStyled component="span">{totalCalories} kcal</TextStyled>
</Stack>
</Toolbar>
</Container>
</AppBar>
<>
<Tooltip title="Back to pages list">
<IconButton component={RouterLink} to="/pages" sx={{ marginRight: 1 }}>
<ArrowBackIcon />
</IconButton>
</Tooltip>
<Stack direction="row" spacing={2} justifyContent="space-between" width="100%">
<TextStyled component="h1">{formatDate(new Date(page.date))}</TextStyled>
<TextStyled component="span">{totalCalories} kcal</TextStyled>
</Stack>
</>
);
};
3 changes: 1 addition & 2 deletions src/frontend/src/pages/ui/PageDetailPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,7 @@ export const Component: FC = () => {

return (
<PrivateLayout
withAdditionalNavigation
header={
subheader={
getPageByIdQuery.data && <PageDetailHeader page={getPageByIdQuery.data.currentPage} />
}
>
Expand Down
3 changes: 2 additions & 1 deletion src/frontend/src/shared/constants.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
export const APP_BAR_HEIGHT = 66;
export const APP_BAR_HEIGHT_XS = 56;
export const APP_BAR_HEIGHT_SM = 64;

export const SIDEBAR_DRAWER_WIDTH = 256;
50 changes: 44 additions & 6 deletions src/frontend/src/shared/ui/AppShell.tsx
Original file line number Diff line number Diff line change
@@ -1,41 +1,79 @@
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';
import { APP_BAR_HEIGHT_SM, APP_BAR_HEIGHT_XS, SIDEBAR_DRAWER_WIDTH } from '../constants';

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

export const AppShell: FC<Props> = ({
children,
withNavigationProgress,
withAdditionalNavigation,
withSidebar,
header,
subheader,
subheaderElevation,
}) => (
<>
{header && (
<AppBar variant="outlined">
<AppBar>
<Box component={Toolbar} disableGutters px={{ xs: 1, sm: 2, md: 1 }}>
{header}
</Box>
</AppBar>
)}
{subheader && (
<AppBar
position="sticky"
elevation={subheaderElevation}
component={Box}
color="inherit"
ml={{
xs: 0,
md: withSidebar ? `${SIDEBAR_DRAWER_WIDTH}px` : 0,
}}
width={{
xs: '100%',
md: withSidebar ? `calc(100% - ${SIDEBAR_DRAWER_WIDTH}px)` : '100%',
}}
sx={{
top: {
xs: APP_BAR_HEIGHT_XS,
sm: APP_BAR_HEIGHT_SM,
},
}}
>
<Container disableGutters>
<Box
component={Toolbar}
disableGutters
pl={{ xs: 1, sm: 2, md: 1 }}
pr={{ xs: 2, sm: 3 }}
>
{subheader}
</Box>
</Container>
</AppBar>
)}
{withNavigationProgress && (
<LinearProgress
sx={{
position: 'absolute',
top: APP_BAR_HEIGHT,
top: {
xs: APP_BAR_HEIGHT_XS,
sm: APP_BAR_HEIGHT_SM,
},
width: '100%',
}}
/>
)}
<Box
component="main"
pt={withAdditionalNavigation ? 0 : 3}
pt={subheader ? 0 : 3}
pb={3}
ml={{
xs: 0,
Expand Down
24 changes: 13 additions & 11 deletions src/frontend/src/widgets/layout/ui/PrivateLayout.tsx
Original file line number Diff line number Diff line change
@@ -1,34 +1,36 @@
import { type Theme, useMediaQuery } from '@mui/material';
import { type Theme, useMediaQuery, useScrollTrigger } from '@mui/material';
import { type PropsWithChildren, type FC, type ReactElement } from 'react';
import { useAuthStatusCheckEffect } from '@/features/auth';
import { APP_BAR_HEIGHT_SM, APP_BAR_HEIGHT_XS } from '@/shared/constants';
import { useToggle } from '@/shared/hooks';
import { AppShell } from '@/shared/ui';
import { NavigationBar } from '@/widgets/navbar';
import { useNavigationProgress } from '../lib';

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

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

const pageScrolled = useScrollTrigger({
threshold: (sm ? APP_BAR_HEIGHT_SM : APP_BAR_HEIGHT_XS) / 2,
disableHysteresis: true,
});

useAuthStatusCheckEffect();

return (
<AppShell
withNavigationProgress={navigationProgressVisible}
withAdditionalNavigation={withAdditionalNavigation}
withSidebar={menuOpened}
header={
<>
<NavigationBar menuOpened={menuOpened} toggleMenu={toggleMenu} />
{header}
</>
}
header={<NavigationBar menuOpened={menuOpened} toggleMenu={toggleMenu} />}
subheader={subheader}
subheaderElevation={pageScrolled ? 1 : 0}
>
{children}
</AppShell>
Expand Down
9 changes: 7 additions & 2 deletions src/frontend/src/widgets/navbar/ui/MobileMenu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import {
} from '@mui/material';
import { type FC, useState } from 'react';
import { Link } from 'react-router-dom';
import { APP_BAR_HEIGHT } from '@/shared/constants';
import { APP_BAR_HEIGHT_SM } from '@/shared/constants';
import { APP_NAME, NAV_LINKS } from '../lib';

export const MobileMenu: FC = () => {
Expand Down Expand Up @@ -51,7 +51,12 @@ export const MobileMenu: FC = () => {
<IconButton size="large" aria-label="Close menu" onClick={handleMenuToggle}>
<CloseIcon />
</IconButton>
<Box display="flex" justifyContent="center" alignItems="center" height={APP_BAR_HEIGHT}>
<Box
display="flex"
justifyContent="center"
alignItems="center"
height={APP_BAR_HEIGHT_SM}
>
<Typography
sx={theme => ({
fontSize: theme.typography.h1.fontSize,
Expand Down
11 changes: 3 additions & 8 deletions src/frontend/src/widgets/navbar/ui/NavigationBar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import {
} from '@mui/material';
import { type FC } from 'react';
import { Form } from 'react-router-dom';
import { APP_BAR_HEIGHT, SIDEBAR_DRAWER_WIDTH } from '@/shared/constants';
import { APP_BAR_HEIGHT_SM, SIDEBAR_DRAWER_WIDTH } from '@/shared/constants';
import { APP_NAME } from '../lib';
import { MenuList } from './MenuList';

Expand Down Expand Up @@ -59,18 +59,13 @@ export const NavigationBar: FC<Props> = ({ menuOpened, toggleMenu }) => {
ModalProps={{ keepMounted: isMobile }}
PaperProps={{
sx: {
marginTop: { xs: 0, md: `${APP_BAR_HEIGHT}px` },
marginTop: { xs: 0, md: `${APP_BAR_HEIGHT_SM}px` },
width: { xs: '75%', md: `${SIDEBAR_DRAWER_WIDTH}px` },
},
component: 'nav',
}}
>
<Box
component={AppBar}
variant="outlined"
position="static"
display={{ xs: 'block', md: 'none' }}
>
<Box component={AppBar} 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}>
Expand Down

0 comments on commit f6104f6

Please sign in to comment.