Responsive layout with temporary and permanent Drawer

"Clipped under the app bar" drawer did not work well on small screens
This commit is contained in:
Stefan Forstenlechner 2022-05-27 23:36:19 +02:00
parent 3e93dbcd75
commit 42799389b5
3 changed files with 77 additions and 7 deletions

View File

@ -3,8 +3,20 @@ import Typography from "@mui/material/Typography";
import React from "react"; import React from "react";
import env from "../env"; import env from "../env";
import AppBar from "@mui/material/AppBar"; import AppBar from "@mui/material/AppBar";
import useMediaQuery from "@mui/material/useMediaQuery";
import { IconButton } from "@mui/material";
import MenuIcon from "@mui/icons-material/Menu";
import CloseIcon from "@mui/icons-material/Close";
import { smallScreenMediaQuery } from "../ImageGalleryLayout";
export const ImageGalleryAppBar = () => { export const ImageGalleryAppBar = ({
open,
onDrawerOpenClick,
}: {
open: boolean;
onDrawerOpenClick: () => void;
}) => {
const smallScreen = !useMediaQuery(smallScreenMediaQuery);
return ( return (
<AppBar <AppBar
position="fixed" position="fixed"
@ -12,6 +24,17 @@ export const ImageGalleryAppBar = () => {
style={{ backgroundColor: env.REACT_APP_APPBAR_COLOR ?? "#1976D2" }} style={{ backgroundColor: env.REACT_APP_APPBAR_COLOR ?? "#1976D2" }}
> >
<Toolbar> <Toolbar>
{smallScreen && (
<IconButton
color="inherit"
aria-label="open drawer"
onClick={onDrawerOpenClick}
edge="start"
sx={{ mr: 2 }}
>
{open && smallScreen ? <CloseIcon /> : <MenuIcon />}
</IconButton>
)}
<Typography variant="h6" noWrap component="div"> <Typography variant="h6" noWrap component="div">
{env.REACT_APP_TITLE ?? "Simple Picture Gallery"} {env.REACT_APP_TITLE ?? "Simple Picture Gallery"}
</Typography> </Typography>

View File

@ -6,6 +6,9 @@ import { useLocation, useNavigate } from "react-router-dom";
import React, { useState } from "react"; import React, { useState } from "react";
import { Folders } from "./models"; import { Folders } from "./models";
import Toolbar from "@mui/material/Toolbar"; import Toolbar from "@mui/material/Toolbar";
import { useTheme } from "@mui/material";
import useMediaQuery from "@mui/material/useMediaQuery";
import { smallScreenMediaQuery } from "../ImageGalleryLayout";
function getDefaultExpanded(pathname: string): string[] { function getDefaultExpanded(pathname: string): string[] {
const pathParts = []; const pathParts = [];
@ -105,23 +108,52 @@ function GenerateTreeView({ root }: { root: Folders }) {
} }
export const ImageGalleryDrawer = ({ export const ImageGalleryDrawer = ({
open,
drawerWidth, drawerWidth,
folder, folder,
handleDrawerToggle,
}: { }: {
open: boolean;
drawerWidth: number; drawerWidth: number;
folder: Folders; folder: Folders;
handleDrawerToggle: () => void;
}) => { }) => {
return ( const theme = useTheme();
const smallScreen = !useMediaQuery(smallScreenMediaQuery);
const drawerContent = (
<>
<Toolbar sx={{ marginBottom: 3 }} />
<GenerateTreeView root={folder} />
</>
);
return smallScreen ? (
<Drawer
variant="temporary"
anchor={theme.direction === "rtl" ? "right" : "left"}
open={open}
onClose={handleDrawerToggle}
style={{ width: drawerWidth }}
ModalProps={{
keepMounted: true, // Better open performance on mobile.
}}
>
{drawerContent}
</Drawer>
) : (
<Drawer <Drawer
variant="permanent" variant="permanent"
sx={{ sx={{
width: drawerWidth, width: drawerWidth,
flexShrink: 0, flexShrink: 0,
[`& .MuiDrawer-paper`]: { width: drawerWidth, boxSizing: "border-box" }, [`& .MuiDrawer-paper`]: {
width: drawerWidth,
boxSizing: "border-box",
},
}} }}
> >
<Toolbar /> {drawerContent}
<GenerateTreeView root={folder} />
</Drawer> </Drawer>
); );
}; };

View File

@ -10,11 +10,14 @@ import { Spinner } from "./ImageGallery/Spinner";
import Toolbar from "@mui/material/Toolbar"; import Toolbar from "@mui/material/Toolbar";
const drawerWidth = 240; const drawerWidth = 240;
export const smallScreenMediaQuery = `(min-width:${drawerWidth * 3}px)`;
function ImageGalleryLayout() { function ImageGalleryLayout() {
const [drawerOpen, setDrawerOpen] = useState(false);
const [error, setError] = useState(false); const [error, setError] = useState(false);
const [imagesLoaded, setImagesLoaded] = useState(false); const [imagesLoaded, setImagesLoaded] = useState(false);
const [images, setImages] = useState<ImageWithThumbnail[]>([]); const [images, setImages] = useState<ImageWithThumbnail[]>([]);
const [folders, setFolders] = useState<Folders>({ const [folders, setFolders] = useState<Folders>({
name: "Home", name: "Home",
fullPath: "/", fullPath: "/",
@ -25,6 +28,10 @@ function ImageGalleryLayout() {
const location = useLocation(); const location = useLocation();
const navigate = useNavigate(); const navigate = useNavigate();
function handleDrawerToggle() {
setDrawerOpen(!drawerOpen);
}
useEffect(() => { useEffect(() => {
setImages([]); setImages([]);
setError(false); setError(false);
@ -63,8 +70,16 @@ function ImageGalleryLayout() {
return ( return (
<Box sx={{ display: "flex" }}> <Box sx={{ display: "flex" }}>
<CssBaseline /> <CssBaseline />
<ImageGalleryAppBar /> <ImageGalleryAppBar
<ImageGalleryDrawer drawerWidth={drawerWidth} folder={folders} /> open={drawerOpen}
onDrawerOpenClick={handleDrawerToggle}
/>
<ImageGalleryDrawer
open={drawerOpen}
drawerWidth={drawerWidth}
folder={folders}
handleDrawerToggle={handleDrawerToggle}
/>
<Box component="main" sx={{ flexGrow: 1, p: 3 }}> <Box component="main" sx={{ flexGrow: 1, p: 3 }}>
<Toolbar /> <Toolbar />
{imagesLoaded ? <ImageGallery images={images} /> : <Spinner />} {imagesLoaded ? <ImageGallery images={images} /> : <Spinner />}