How to create a Swipeable Drawer in Material UI

H
andrewgbliss
9 months ago

This article will cover how to create a Swipeable Drawer in Material UI

. . .

Github repo

https://github.com/EntryLevelDeveloperTraining/material-ui-workshop

What is a Swipeable Drawer

In the world of Web Applications and JavaScript many developers add a hamburger menu that when clicked on will open up a drawer. A drawer is an HTML element that is hidden off screen until an action open its up and shows either links or settings. Making is swipeable is useful for mobile devices where the user can swipe to open or close it.

SwipeableDrawer Component

Material UI has a robust set of components we can use. Luckily they have already implemented a Swipeable Drawer. Let's look at a basic implementation of it.

import { useState } from 'react';
import SwipeableDrawer from '@material-ui/core/SwipeableDrawer';

export default function Drawer() {
  const [open, setOpen] = useState<boolean>(false);
  return (
    <div>
      <SwipeableDrawer
        anchor="left"
        open={open}
        onClose={() => setOpen(false)}
        onOpen={() => {}}
      >
          This is what is in the drawer
      </SwipeableDrawer>
    </div>
  );
}

This is basically all you need to create a Swipeable Drawer. We use a React useState hook to say whether or not the Drawer is open on closed. Now let's add in a hamburger menu to open it when it's clicked.

import { useState } from 'react';
import Box from '@material-ui/core/Box';
import SwipeableDrawer from '@material-ui/core/SwipeableDrawer';
import List from '@material-ui/core/List';
import ListItem from '@material-ui/core/ListItem';
import ListItemText from '@material-ui/core/ListItemText';
import Divider from '@material-ui/core/Divider';
import IconButton from '@material-ui/core/IconButton';
import MenuIcon from '@material-ui/icons/Menu';
import { makeStyles } from '@material-ui/core/styles';
import { useRouter } from 'next/router';

const useStyles = makeStyles({
  list: {
    width: 250,
  },
});

export default function Drawer() {
  const classes = useStyles();
  const router = useRouter();
  const [open, setOpen] = useState<boolean>(false);
  return (
    <div>
      <IconButton
        edge="start"
        color="inherit"
        aria-label="open drawer"
        onClick={() => setOpen(true)}
      >
        <MenuIcon />
      </IconButton>
      <SwipeableDrawer
        anchor="left"
        open={open}
        onClose={() => setOpen(false)}
        onOpen={() => {}}
      >
        <div className={classes.list}>
          <Box textAlign="center" p={2}>
            Components
          </Box>
          <Divider />
          <List>
            <ListItem button onClick={() => router.push('/container')}>
              <ListItemText primary={'Container'} />
            </ListItem>
            <ListItem button onClick={() => router.push('/grid')}>
              <ListItemText primary={'Grid'} />
            </ListItem>
            <ListItem button onClick={() => router.push('/box')}>
              <ListItemText primary={'Box'} />
            </ListItem>
            <ListItem button onClick={() => router.push('/cards')}>
              <ListItemText primary={'Cards'} />
            </ListItem>
          </List>
        </div>
      </SwipeableDrawer>
    </div>
  );
}

Now we have added the MenuIcon, and when clicked it sets the state to open. We also added some styles to make the drawer wide. If you want to make this a re-usable component then you can accept a children prop and dynamically generate the contents of the drawer, then be able to use this wherever in your application.

In my implementation I am also using NextJs, that when you click on a link, from within the drawer, it will take you to that page in my app.

Conclusion

Added a swipeable drawer will make your app look and feel like a native application for mobile devices.


H
andrewgbliss
9 months ago