Skip to content

Commit f38b520

Browse files
committed
Make game navigation responsive on mobile
1 parent 0e534c4 commit f38b520

3 files changed

Lines changed: 95 additions & 30 deletions

File tree

src/Games.jsx

Lines changed: 50 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import cookie from 'react-cookies';
55
import alphanumSort from 'alphanum-sort';
66

77
import Autocomplete from '@mui/material/Autocomplete';
8+
import Box from '@mui/material/Box';
89
import Snackbar from '@mui/material/Snackbar';
910
import TextField from '@mui/material/TextField';
1011

@@ -18,13 +19,6 @@ import api from './api.js';
1819
const INIT_LOAD_WAIT_TIMEOUT = 100;
1920

2021
const styles = {
21-
developersHeader: {
22-
alignItems: 'center',
23-
boxSizing: 'border-box',
24-
display: 'flex',
25-
justifyContent: 'space-between',
26-
margin: '24px 40px 0',
27-
},
2822
developersTitle: {
2923
fontSize: '1.25rem',
3024
fontWeight: 500,
@@ -36,12 +30,20 @@ const styles = {
3630
alignItems: 'start',
3731
boxSizing: 'border-box',
3832
display: 'grid',
39-
gap: 20,
33+
gap: {
34+
sm: 2.5,
35+
xs: 2,
36+
},
4037
// Equal columns that share the row, so cards are all the same width and
41-
// the grid fills edge to edge. The 40px side padding matches the game
42-
// settings box above, lining both up on the left and right.
43-
gridTemplateColumns: 'repeat(auto-fill, minmax(300px, 1fr))',
44-
padding: '20px 40px',
38+
// the grid fills edge to edge. min(100%, 300px) keeps the track from
39+
// exceeding the viewport on phones narrower than 300px (no h-scroll).
40+
gridTemplateColumns: 'repeat(auto-fill, minmax(min(100%, 300px), 1fr))',
41+
// Side padding matches the game settings box above on desktop; tighter
42+
// on mobile so cards use the full screen width.
43+
padding: {
44+
sm: '20px 40px',
45+
xs: '16px',
46+
},
4547
width: '100%',
4648
},
4749
};
@@ -401,8 +403,16 @@ class Games extends React.Component {
401403
);
402404
} }
403405
sx = { {
404-
mr: 2,
405-
width: 260,
406+
// Grow to fill the mobile actions row beside
407+
// the Add-game button; fixed width on desktop.
408+
flexGrow: {
409+
sm: 0,
410+
xs: 1,
411+
},
412+
minWidth: 0,
413+
width: {
414+
sm: 260,
415+
},
406416
} }
407417
value = { currentGame }
408418
/>
@@ -419,15 +429,27 @@ class Games extends React.Component {
419429
/>
420430
}
421431
{ currentGame &&
422-
<div
423-
style = { styles.developersHeader }
432+
<Box
433+
sx = { {
434+
alignItems: 'center',
435+
display: 'flex',
436+
flexWrap: 'wrap',
437+
gap: 2,
438+
justifyContent: 'space-between',
439+
// Tighter side margins on mobile so the filter and
440+
// Add-developer button aren't cramped into the middle.
441+
m: {
442+
sm: '24px 40px 0',
443+
xs: '16px 16px 0',
444+
},
445+
} }
424446
>
425-
<div
426-
style = { {
447+
<Box
448+
sx = { {
427449
alignItems: 'center',
428450
display: 'flex',
429451
flex: 1,
430-
gap: 16,
452+
gap: 2,
431453
minWidth: 0,
432454
} }
433455
>
@@ -442,20 +464,23 @@ class Games extends React.Component {
442464
placeholder = { 'nick, name or group' }
443465
size = { 'small' }
444466
sx = { {
445-
width: 260,
467+
// Grow to fill on mobile, capped on desktop.
468+
flexGrow: 1,
469+
maxWidth: 260,
470+
minWidth: 0,
446471
} }
447472
value = { this.state.filter }
448473
variant = { 'outlined' }
449474
/>
450-
</div>
475+
</Box>
451476
{ addNode }
452-
</div>
477+
</Box>
453478
}
454-
<div
455-
style = { styles.wrapper }
479+
<Box
480+
sx = { styles.wrapper }
456481
>
457482
{ this.getDevelopers() }
458-
</div>
483+
</Box>
459484
<Snackbar
460485
autoHideDuration = { 4000 }
461486
message = { this.state.snackbarText }

src/Header.jsx

Lines changed: 39 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,25 @@ const Header = ( props ) => {
1818
color = { 'default' }
1919
position = { 'static' }
2020
>
21-
<Toolbar>
21+
<Toolbar
22+
sx = { {
23+
// On phones the title + tabs + actions don't fit one row, so
24+
// let the actions wrap onto their own full-width row below
25+
// (md+ keeps everything on a single line).
26+
flexWrap: {
27+
md: 'nowrap',
28+
xs: 'wrap',
29+
},
30+
gap: {
31+
md: 0,
32+
xs: 1,
33+
},
34+
py: {
35+
md: 0,
36+
xs: 1,
37+
},
38+
} }
39+
>
2240
<Typography
2341
noWrap
2442
onClick = { () => {
@@ -28,7 +46,10 @@ const Header = ( props ) => {
2846
cursor: 'pointer',
2947
flexShrink: 0,
3048
fontWeight: 700,
31-
mr: 4,
49+
mr: {
50+
md: 4,
51+
xs: 2,
52+
},
3253
} }
3354
variant = { 'h6' }
3455
>
@@ -40,10 +61,23 @@ const Header = ( props ) => {
4061
/>
4162
<Box
4263
sx = { {
43-
flexGrow: 1,
64+
alignItems: 'center',
65+
display: 'flex',
66+
// Fill the row and right-align on desktop; drop to a full
67+
// width row of its own on mobile.
68+
flexBasis: {
69+
md: 'auto',
70+
xs: '100%',
71+
},
72+
gap: 1,
73+
justifyContent: 'flex-end',
74+
ml: {
75+
md: 'auto',
76+
},
4477
} }
45-
/>
46-
{ props.actions }
78+
>
79+
{ props.actions }
80+
</Box>
4781
</Toolbar>
4882
</AppBar>
4983
);

src/NavTabs.jsx

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,17 +9,23 @@ import Tabs from '@mui/material/Tabs';
99
const NavTabs = ( props ) => {
1010
return (
1111
<Tabs
12+
allowScrollButtonsMobile
1213
onChange = { ( event, value ) => {
1314
props.onNavigate( value );
1415
} }
16+
scrollButtons = { 'auto' }
1517
sx = { {
18+
// Scrollable so the four tabs never squeeze the title/actions on
19+
// a narrow phone — they scroll horizontally instead.
20+
maxWidth: '100%',
1621
mr: 2,
1722
'& .MuiTab-root': {
1823
minHeight: 64,
1924
textTransform: 'none',
2025
},
2126
} }
2227
value = { props.view }
28+
variant = { 'scrollable' }
2329
>
2430
<Tab
2531
label = { 'Dashboard' }

0 commit comments

Comments
 (0)