Skip to content

Instantly share code, notes, and snippets.

@tanpld
Last active May 19, 2020 16:47
Show Gist options
  • Save tanpld/1b1ea21aa9d81e9a4e95624a82081ede to your computer and use it in GitHub Desktop.
Save tanpld/1b1ea21aa9d81e9a4e95624a82081ede to your computer and use it in GitHub Desktop.
Responsive + Persistent Drawer + AppBar Layout - React Component MaterialUI
import React, { useState, useEffect } from "react";
import {
makeStyles,
Theme,
createStyles,
useTheme,
} from "@material-ui/core/styles";
import AppBar from "@material-ui/core/AppBar";
import Toolbar from "@material-ui/core/Toolbar";
import IconButton from "@material-ui/core/IconButton";
import MenuIcon from "@material-ui/icons/Menu";
import Drawer from "@material-ui/core/Drawer";
import List from "@material-ui/core/List";
import ListItem from "@material-ui/core/ListItem";
import ListItemIcon from "@material-ui/core/ListItemIcon";
import ListItemText from "@material-ui/core/ListItemText";
import Typography from "@material-ui/core/Typography";
import Divider from "@material-ui/core/Divider";
import ChevronLeftIcon from "@material-ui/icons/ChevronLeft";
import ChevronRightIcon from "@material-ui/icons/ChevronRight";
import MailIcon from "@material-ui/icons/Mail";
import useMediaQuery from "@material-ui/core/useMediaQuery";
import clsx from "clsx";
interface Props {
className: string;
}
const drawerWidth = 300;
const useStyles = makeStyles((theme: Theme) =>
createStyles({
root: {
display: "flex",
},
appBar: {
transition: theme.transitions.create(["margin", "width"], {
easing: theme.transitions.easing.sharp,
duration: theme.transitions.duration.leavingScreen,
}),
},
appBarShift: {
width: `calc(100% - ${drawerWidth}px)`,
marginLeft: drawerWidth,
transition: theme.transitions.create(["margin", "width"], {
easing: theme.transitions.easing.easeOut,
duration: theme.transitions.duration.enteringScreen,
}),
},
menuButton: {
marginRight: theme.spacing(2),
},
hide: {
display: "none",
},
drawer: {
flexShrink: 0,
},
drawerHide: {
width: 0,
},
drawerPaper: {
width: drawerWidth,
},
drawerHeader: {
display: "flex",
alignItems: "center",
padding: theme.spacing(0, 1),
// necessary for content to be below app bar
...theme.mixins.toolbar,
justifyContent: "flex-end",
},
content: {
flexGrow: 1,
padding: theme.spacing(3),
transition: theme.transitions.create("margin", {
easing: theme.transitions.easing.sharp,
duration: theme.transitions.duration.leavingScreen,
}),
},
contentShift: {
transition: theme.transitions.create("margin", {
easing: theme.transitions.easing.easeOut,
duration: theme.transitions.duration.enteringScreen,
}),
marginLeft: drawerWidth,
},
})
);
function Layout(props: Props) {
const classes = useStyles();
const theme = useTheme();
const smallScreen = useMediaQuery(theme.breakpoints.down("sm"));
const [isSidebarOpen, setSidebarOpen] = useState(!smallScreen);
useEffect(() => {
setSidebarOpen(!smallScreen);
}, [smallScreen]);
function handleToggleSidebar(open: boolean) {
setSidebarOpen(open);
}
return (
<div className={classes.root}>
<AppBar
position="fixed"
className={clsx(classes.appBar, {
[classes.appBarShift]: isSidebarOpen,
})}
>
<Toolbar>
<IconButton
color="inherit"
aria-label="open drawer"
onClick={() => handleToggleSidebar(true)}
edge="start"
className={clsx(classes.menuButton, isSidebarOpen && classes.hide)}
>
<MenuIcon />
</IconButton>
<Typography variant="h6" noWrap>
Persistent drawer
</Typography>
</Toolbar>
</AppBar>
<Drawer
className={clsx(classes.drawer, {
[classes.drawerHide]: !isSidebarOpen,
})}
variant="persistent"
anchor="left"
open={isSidebarOpen}
classes={{
paper: classes.drawerPaper,
}}
>
<div className={classes.drawerHeader}>
<IconButton onClick={() => handleToggleSidebar(false)}>
{theme.direction === "ltr" ? (
<ChevronLeftIcon />
) : (
<ChevronRightIcon />
)}
</IconButton>
</div>
<Divider />
<List>
{["Inbox", "Starred", "Send email", "Drafts"].map((text, index) => (
<ListItem button key={text}>
<ListItemIcon>
<MailIcon />
</ListItemIcon>
<ListItemText primary={text} />
</ListItem>
))}
</List>
<Divider />
<List>
{["All mail", "Trash", "Spam"].map((text, index) => (
<ListItem button key={text}>
<ListItemIcon>
<MailIcon />
</ListItemIcon>
<ListItemText primary={text} />
</ListItem>
))}
</List>
</Drawer>
<main
className={clsx(classes.content, {
[classes.contentShift]: isSidebarOpen && !smallScreen,
})}
>
<div className={classes.drawerHeader} />
<Typography paragraph>
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do
eiusmod tempor incididunt ut labore et dolore magna aliqua. Rhoncus
dolor purus non enim praesent elementum facilisis leo vel. Risus at
ultrices mi tempus imperdiet. Semper risus in hendrerit gravida rutrum
quisque non tellus. Convallis convallis tellus id interdum velit
laoreet id donec ultrices. Odio morbi quis commodo odio aenean sed
adipiscing. Amet nisl suscipit adipiscing bibendum est ultricies
integer quis. Cursus euismod quis viverra nibh cras. Metus vulputate
eu scelerisque felis imperdiet proin fermentum leo. Mauris commodo
quis imperdiet massa tincidunt. Cras tincidunt lobortis feugiat
vivamus at augue. At augue eget arcu dictum varius duis at consectetur
lorem. Velit sed ullamcorper morbi tincidunt. Lorem donec massa sapien
faucibus et molestie ac.
</Typography>
<Typography paragraph>
Consequat mauris nunc congue nisi vitae suscipit. Fringilla est
ullamcorper eget nulla facilisi etiam dignissim diam. Pulvinar
elementum integer enim neque volutpat ac tincidunt. Ornare suspendisse
sed nisi lacus sed viverra tellus. Purus sit amet volutpat consequat
mauris. Elementum eu facilisis sed odio morbi. Euismod lacinia at quis
risus sed vulputate odio. Morbi tincidunt ornare massa eget egestas
purus viverra accumsan in. In hendrerit gravida rutrum quisque non
tellus orci ac. Pellentesque nec nam aliquam sem et tortor. Habitant
morbi tristique senectus et. Adipiscing elit duis tristique
sollicitudin nibh sit. Ornare aenean euismod elementum nisi quis
eleifend. Commodo viverra maecenas accumsan lacus vel facilisis. Nulla
posuere sollicitudin aliquam ultrices sagittis orci a.
</Typography>
</main>
</div>
);
}
export default Layout;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment