8000 fix responsive appbar to work with mobile · devel0/example-webapp-with-auth@8afce94 · GitHub
[go: up one dir, main page]

Skip to content

Commit 8afce94

Browse files
committed
fix responsive appbar to work with mobile
1 parent a4ab52d commit 8afce94

File tree

5 files changed

+77
-53
lines changed

5 files changed

+77
-53
lines changed

src/frontend/src/components/Layout.tsx

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,15 @@ import { useAppDispatch, useAppSelector } from '../redux/hooks/hooks'
55
import { GlobalState } from '../redux/states/GlobalState'
66
import { APP_URL_Login, APP_URL_Users, DEFAULT_SIZE_1_REM, DEFAULT_SIZE_0_5_REM, LOCAL_STORAGE_CURRENT_USER_NFO, LOCAL_STORAGE_REFRESH_TOKEN_EXPIRE, RENEW_REFRESH_TOKEN_BEFORE_EXPIRE_SEC, APP_URL_Home } from '../constants/general'
77
import { 8000 useEffect, useState } from 'react'
8-
import { setLoggedOut, setSuccessfulLogin, setUrlWanted } from '../redux/slices/globalSlice'
8+
import { setIsMobile, setLoggedOut, setSuccessfulLogin, setUrlWanted } from '../redux/slices/globalSlice'
99
import { Box, Button, CssBaseline, LinearProgress } from '@mui/material'
1010
import ResponsiveAppBar, { AppBarItem } from './ResponsiveAppBar'
1111
import { AboutDialog } from '../dialogs/AboutDialog';
1212
import { CurrentUserNfo } from '../types/CurrentUserNfo';
1313
import { authApi } from '../axios.manager';
1414
import { AxiosError, HttpStatusCode } from 'axios';
15-
import { handleApiException } from '../utils/utils';
15+
import { computeIsMobile, handleApiException } from '../utils/utils';
16+
import { useEventListener } from 'usehooks-ts';
1617

1718
type Props = {
1819
child: JSX.Element
@@ -92,6 +93,10 @@ const MainLayout = (props: Props) => {
9293
}
9394
}, [location.pathname, global.currentUser, global.currentUserInitialized])
9495

96+
useEventListener('resize', () => {
97+
dispatch(setIsMobile(computeIsMobile()))
98+
})
99+
95100
const menuPages: AppBarItem[] = [
96101
{
97102
hidden: !global.currentUserCanManageUsers,

src/frontend/src/components/ResponsiveAppBar.tsx

Lines changed: 55 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -1,38 +1,36 @@
11
import * as React from 'react';
2+
import { Link } from "react-router-dom"
23
import AppBar from '@mui/material/AppBar';
34
import Box from '@mui/material/Box';
45
import Toolbar from '@mui/material/Toolbar';
56
import IconButton from '@mui/material/IconButton';
67
import Typography from '@mui/material/Typography';
78
import Menu from '@mui/material/Menu';
89
import MenuIcon from '@mui/icons-material/Menu';
9-
import Container from '@mui/material/Container';
1010
import Avatar from '@mui/material/Avatar';
11-
import Button from '@mui/material/Button';
1211
import Tooltip from '@mui/material/Tooltip';
1312
import MenuItem from '@mui/material/MenuItem';
14-
import AdbIcon from '@mui/icons-material/Adb';
1513
import AppLogo from '../images/app-icon.svg?react'
16-
import { APP_LOGO_TEXT, APP_URL_Home, DEFAULT_SIZE_1_REM, DEFAULT_SIZE_0_5_REM } from '../constants/general';
14+
import { APP_LOGO_TEXT, DEFAULT_SIZE_1_REM, DEFAULT_SIZE_0_5_REM, APP_URL_Home } from '../constants/general';
1715
import { useAppDispatch, useAppSelector } from '../redux/hooks/hooks';
1816
import { GlobalState } from '../redux/states/GlobalState';
1917
import { firstLetter, LinkButton } from '../utils/utils';
2018
import ThemeChooser from './ThemeChooser';
21-
import { Link, useNavigate } from 'react-router-dom';
19+
import { useNavigate } from 'react-router-dom';
2220
import { useTheme } from '@mui/material';
2321

2422
export interface AppBarItem {
2523
hidden?: boolean,
2624
label: string,
25+
selected?: boolean,
2726
icon?: JSX.Element,
2827
url?: string,
29-
selected?: boolean,
3028
onClick?: () => void,
3129
}
3230

3331
function ResponsiveAppBar(props: {
3432
pages: AppBarItem[],
35-
settings: AppBarItem[]
33+
settings: AppBarItem[]
3634
}) {
3735
const global = useAppSelector<GlobalState>((state) => state.global)
3836
const dispatch = useAppDispatch()
@@ -69,27 +67,29 @@ function ResponsiveAppBar(props: {
6967
DESKTOP LOGO
7068
-----------------------------------------------------------------------
7169
*/}
72-
<Box
73-
sx={{
74-
display: 'flex',
70+
{global.isMobile === false && <div
71+
onClick={() => navigate(APP_URL_Home)}
72+
style={{
73+
display: 'flex',
74+
cursor: 'pointer'
7575
}}>
7676

77-
<LinkButton
78-
LinkComponent={Link}
79-
to={APP_URL_Home}
80-
sx={{
81-
display: { xs: 'none', md: 'flex' },
82-
mr: 2
83-
}} >
77+
<Link
78+
style={{
79+
// display: { xs: 'none', md: 'flex' },
80+
marginRight: DEFAULT_SIZE_0_5_REM
81+
}}
82+
to={APP_URL_Home}>
8483
<AppLogo width='100%' height='50px' />
85-
</LinkButton>
84+
</Link>
8685

8786
{APP_LOGO_TEXT && <Typography
8887
variant="h6"
8988
noWrap
9089
sx={{
9190
mr: 2,
92-
display: { xs: 'none', md: 'flex' },
91+
display: 'flex',
92+
// display: { xs: 'none', md: 'flex' },
9393
alignSelf: 'center',
9494
fontFamily: 'monospace',
9595
fontWeight: 700,
@@ -100,18 +100,19 @@ function ResponsiveAppBar(props: {
100100
>
101101
{APP_LOGO_TEXT}
102102
</Typography>}
103-
</Box>
103+
</div>}
104104

105105
{/*
106106
-----------------------------------------------------------------------
107107
DESKTOP MENU
108108
-----------------------------------------------------------------------
109109
*/}
110-
<Box sx={{
110+
{global.isMobile === false && <Box sx={{
111111
flexGrow: 1,
112-
display: { xs: 'none', md: 'flex' }
112+
display: 'flex'
113113
}}>
114114
{pages.filter(w => w.hidden !== true).map((page, pageIdx) => (
115+
115116
<LinkButton
116117
LinkComponent={Link}
117118
to={page.url ?? ''}
@@ -129,14 +130,14 @@ function ResponsiveAppBar(props: {
129130
</Typography>
130131
</LinkButton>
131132
))}
132-
</Box>
133+
</Box>}
133134

134135
{/*
135136
-----------------------------------------------------------------------
136137
MOBILE MENU
137138
-----------------------------------------------------------------------
138139
*/}
139-
<Box sx={{ flexGrow: 0, display: { xs: 'flex', md: 'none' } }}>
140+
{global.isMobile && <Box sx={{ flexGrow: 0, display: 'flex', gap: DEFAULT_SIZE_0_5_REM, alignItems: 'center' }}>
140141
<IconButton
141142
size="large"
142143
aria-label="account of current user"
@@ -147,6 +148,22 @@ function ResponsiveAppBar(props: {
147148
>
148149
<MenuIcon />
149150
</IconButton>
151+
152+
<IconButton
153+
size="large"
154+
aria-label="account of current user"
155+
aria-controls="menu-appbar"
156+
aria-haspopup="true"
157+
onClick={() => navigate(APP_URL_Home)}
158+
color="inherit"
159+
>
160+
<Box sx={{
161+
display: 'flex', gap: DEFAULT_SIZE_0_5_REM
162+
}}>
163+
<AppLogo width='100%' height='50px' />
164+
</Box>
165+
</IconButton>
166+
150167
<Menu
151168
id="menu-appbar"
152169
anchorEl={anchorElNav}
@@ -162,28 +179,34 @@ function ResponsiveAppBar(props: {
162179
open={Boolean(anchorElNav)}
163180
onClose={handleCloseNavMenu}
164181
sx={{
165-
display: { xs: 'block', md: 'none' },
182+
display: 'block'
183+
// display: { xs: 'block', md: 'none' },
166184
}}
167185
>
168186
{pages.filter(w => w.hidden !== true).map((page, pageIdx) => (
169187
<MenuItem
170188
key={`mob-page-${pageIdx}`}
171189
onClick={() => {
190+
if (page.url)
191+
navigate(page.url ?? '')
172192
page.onClick?.()
173193
handleCloseNavMenu()
174194
}}>
175-
<Typography textAlign="center">{page.label}</Typography>
195+
<Box sx={{ display: 'flex', gap: DEFAULT_SIZE_0_5_REM }}>
196+
{page.icon}
197+
<Typography textAlign="center">{page.label}</Typography>
198+
</Box>
176199
</MenuItem>
177200
))}
178201
</Menu>
179-
</Box>
202+
</Box>}
180203

181204
{/*
182205
-----------------------------------------------------------------------
183206
MOBILE LOGO
184207
-----------------------------------------------------------------------
185208
*/}
186-
<div
209+
{global.isMobile && <div
187210
onClick={() => navigate(APP_URL_Home)}
188211
style={{
189212
display: 'flex',
@@ -194,36 +217,16 @@ function ResponsiveAppBar(props: {
194217
<Box sx={{
195218
display: 'flex',
196219
width: '100%',
197-
justifyContent: 'center'
220+
justifyContent: 'flex-start'
198221
}}>
199222

200223
<Box sx={{ display: 'flex' }}>
201224

202-
<Box mr={1} sx={{ display: { xs: 'flex', md: 'none' }, mr: 1 }}>
203-
<AppLogo width='100%' height='50px' />
204-
</Box>
205-
206-
{APP_LOGO_TEXT && <Typography
207-
variant="h5"
208-
noWrap
209-
sx={{
210-
mr: 2,
211-
display: { xs: 'flex', md: 'none' },
212-
alignSelf: 'center',
213-
fontFamily: 'monospace',
214-
fontWeight: 700,
215-
letterSpacing: '.3rem',
216-
color: 'inherit',
217-
textDecoration: 'none',
218-
}}
219-
>
220-
{APP_LOGO_TEXT}
221-
</Typography>}
222225

223226
</Box>
224227

225228
</Box>
226-
</div>
229+
</div>}
227230

228231
{/*
229232
-----------------------------------------------------------------------
@@ -232,6 +235,7 @@ function ResponsiveAppBar(props: {
232235
*/}
233236
<Box sx={{ flexGrow: 0 }}>
234237
<ThemeChooser />
238+
235239
<Tooltip title="Open settings">
236240
<IconButton onClick={handleOpenUserMenu} sx={{ p: 0 }}>
237241
<Avatar>
@@ -272,7 +276,7 @@ function ResponsiveAppBar(props: {
272276
</Box>
273277
</Toolbar>
274278
</Box>
275-
</AppBar>
279+
</AppBar >
276280
);
277281
}
278282
export default ResponsiveAppBar;

src/frontend/src/redux/slices/globalSlice.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,10 @@ export const globalSlice = createSlice({
4646
document.body.style.colorScheme = theme
4747
},
4848

49+
setIsMobile: (state, action: PayloadAction<boolean>) => {
50+
state.isMobile = action.payload
51+
},
52+
4953
},
5054

5155
});
@@ -57,6 +61,7 @@ export const {
5761
setSuccessfulLogin,
5862
setLoggedOut,
5963
setTheme,
64+
setIsMobile
6065

6166
} = globalSlice.actions;
6267

src/frontend/src/redux/states/GlobalState.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { PaletteMode } from "@mui/material";
22
import { LOCAL_STORAGE_CURRENT_USER_NFO, LOCAL_STORAGE_THEME, THEME_INITIAL } from "../../constants/general";
33
import { CurrentUserNfo } from "../../types/CurrentUserNfo";
4+
import { computeIsMobile } from "../../utils/utils";
45

56
export interface GlobalState {
67
theme: PaletteMode;
@@ -11,6 +12,7 @@ export interface GlobalState {
1112
currentUserInitialized: boolean;
1213
currentUserCanManageUsers: boolean;
1314
currentUser: CurrentUserNfo | undefined;
15+
isMobile: boolean
1416
}
1517

1618
// retrieve authenticated user info from local storage
@@ -35,5 +37,6 @@ export const GlobalInitialState: GlobalState = {
3537
currentUserInitialized: false,
3638
currentUserCanManageUsers: false,
3739
currentUser: initialCurrentUser,
40+
isMobile: computeIsMobile()
3841

3942
};

src/frontend/src/utils/utils.tsx

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,3 +106,10 @@ export const setSnack = (nfo: SnackNfo) => {
106106
})
107107

108108
}
109+
110+
export const computeIsMobile = () => {
111+
const w = window.innerWidth
112+
const isMobile = w <= 600
113+
114+
return isMobile
115+
}

0 commit comments

Comments
 (0)
0