React Tutorial: Creating responsive Drawer using Material-UI

responsive drawer
Responsive Drawer

In this article, we are going to build a responsive Drawer that adjusts itself according to screen size using material-UI framework. If you are new visit here for installing and getting started with Material-UI.

In the code below first we will set up a simple drawer then we will add a feature of hiding the drawer according to the screen size.

Let’s get started, open up your text editor, and write the following code:

Drawer

import React from 'react';
import AppBar from '@material-ui/core/AppBar';
import Drawer from '@material-ui/core/Drawer';
import Toolbar from '@material-ui/core/Toolbar';
import Divider from '@material-ui/core/Divider';
import Hidden from '@material-ui/core/Hidden';
import List from '@material-ui/core/List';
import IconButton from '@material-ui/core/IconButton';
import MenuIcon from '@material-ui/icons/Menu';
import ListItem from '@material-ui/core/ListItem';
import ListItemText from '@material-ui/core/ListItemText';
import Typography from '@material-ui/core/Typography';
import {makeStyles} from '@material-ui/core/styles';

import img1 from './img1.jpg';
import img2 from './img2.jpg';

const drawerWidth = 240;
const useStyles = makeStyles((theme) => ({
  drawer: {
          width: drawerWidth,
              flexShrink: 0,
            },
    toolbar : theme.mixins.toolbar,

     content : {
     flexGrow: 1,
    padding: theme.spacing(3),
     marginLeft: 300,
 }
}));

export default function App() {
    const classes = useStyles();

    const drawer  = (
        <div>
            <div>
                <Divider />
                <List>
                    {['Search','Browse','Category'].map((anchor,text) => (
                        <ListItem button key = {anchor}>
                            <ListItemText primary = {anchor}/>
                        </ListItem>
                    ))}
                </List>
                <Divider />
                <List>
                    {['Services','About Us','Contact Us'].map((anchor,text) => (
                        <ListItem button key = {anchor}>
                            <ListItemText primary = {anchor}/>
                        </ListItem>
                    ))}
                </List>
            </div>
        </div>
    )
    return (
        <div>
            <AppBar position = 'fixed'>
                <Toolbar>
                    <Drawer
                    classes={{
                        paper: classes.drawer,
                    }}
                    open
                    variant = 'permanent'
                    >
                    {drawer}
                </Drawer>
                </Toolbar>
            </AppBar>
            <div className={classes.content}>
                <div className={classes.toolbar} />
                <img src={img1} style={{height:'auto' , width:'80%'}}
                    alt = "img1" />
                    <Typography paragraph>
                        I inadvertently went to See's Candy last week (I was
                        in the mall looking for phone repair), and as it turns
                        out, See's Candy now charges a dollar -- a full dollar
                        -- for even the simplest of their wee confection
                        offerings. I bought two chocolate lollipops and two
                        chocolate-caramel-almond things. The total cost was
                        four-something. I mean, the candies were tasty and all,
                        but let's be real: A Snickers bar is fifty cents.
                        After this dollar-per-candy revelation, I may not
                        find myself wandering dreamily back into a See's
                        Candy any time soon.
                    </Typography>

                    <img src={img2} style={{height:'auto' , width:'80%'}} alt = "img1" />
                    <Typography paragraph>
                        Spending time at national parks can be an exciting
                        adventure, but this wasn't the type of excitement she was
                        hoping to experience. As she contemplated the situation
                        she found herself in, she knew she'd gotten herself in a
                        little more than she bargained for. It wasn't often that
                        she found herself in a tree staring down at a pack of
                        wolves that were looking to make her their next meal.
                    </Typography>
              </div>
            </div>

    );
}

In the above code first, we define the width of our drawer which is 240px. Then in the App() function, we have defined our drawer which contains the list of items such as Browser, Category, etc. To make our app visual we have added an AppBar on top of this we will have our drawer. The way we create drawer is by using material-UI Drawer tag. Since our drawer should be visible we pass open props to our Drawer tag. Also, we have passed variant to permanent so that our other content on the page does not get block out.

Next, we write out App content. The classes.toolbar property in the div tag tells that our content should be below the AppBar. Also, our content should have left margin of at least 240px so it does not hide behind our drawer. The output of the following App we something look like this:

Responsive Drawer using materail ui

But if you make your screen smaller you will notice that our Drawer sticks their and content gets smaller and smaller. We don’t want that we want our drawer to automatically hide if the display screen is smaller so that the user can read our content. So to make drawer hide we will be using material-UI Hidden tag.

Modify the code as follows:

Responsive Drawer


import React from 'react';
import AppBar from '@material-ui/core/AppBar';
import Drawer from '@material-ui/core/Drawer';
import Toolbar from '@material-ui/core/Toolbar';
import Divider from '@material-ui/core/Divider';
import Hidden from '@material-ui/core/Hidden';
import List from '@material-ui/core/List';
import IconButton from '@material-ui/core/IconButton';
import MenuIcon from '@material-ui/icons/Menu';
import ListItem from '@material-ui/core/ListItem';
import ListItemText from '@material-ui/core/ListItemText';
import Typography from '@material-ui/core/Typography';
import {makeStyles} from '@material-ui/core/styles';

import img1 from './img1.jpg';
import img2 from './img2.jpg';

const drawerWidth = 240;
const useStyles = makeStyles((theme) => ({
  drawer: {
          width: drawerWidth,
              flexShrink: 0,
            },
toolbar : theme.mixins.toolbar,
 content : {
     flexGrow: 1,
    padding: theme.spacing(3),
    [theme.breakpoints.up('sm')]: {
     marginLeft: 300,
    },
 }
}));

export default function App() {
    const classes = useStyles();
    const [state,setSmallDevice] = React.useState(false);
    const handleSmallDevice = () => {
        setSmallDevice(!state);
    };

    const drawer  = (
        <div>
            <div>
                <Divider />
                <List>
                    {['Search','Browse','Category'].map((anchor,text) => (
                        <ListItem button key = {anchor}>
                            <ListItemText primary = {anchor}/>
                        </ListItem>
                    ))}
                </List>
                <Divider />
                <List>
                    {['Services','About Us','Contact Us'].map((anchor,text) => (
                        <ListItem button key = {anchor}>
                            <ListItemText primary = {anchor}/>
                        </ListItem>
                    ))}
                </List>
            </div>
        </div>
    )
    return (
        <div>
            <AppBar position = 'fixed'>
                <Toolbar>
                   <Hidden smUp implementation="css">
                        <IconButton
                    color="inherit"
                    aria-label = "open drawer"
                    edge = 'start'
                    onClick  = {handleSmallDevice}
                        >  <MenuIcon />
                    </IconButton>
                    <Drawer
                        classes={{
                            paper: classes.drawer,
                        }}
                        open={state}
                        onClose = {handleSmallDevice}
                        >
                            {drawer}
                    </Drawer>
                </Hidden>
              <Hidden xsDown implementation="css"> <Drawer
                    classes={{
                        paper: classes.drawer,
                    }}
                    open
                    variant = 'permanent'
                    >
                    {drawer}
                </Drawer>
            </Hidden>
                </Toolbar>
            </AppBar>
            <div className={classes.content}>
                <div className={classes.toolbar} />
                <img src={img1} style={{height:'auto' , width:'80%'}}
                    alt = "img1" />
                    <Typography paragraph>
                        I inadvertently went to See's Candy last week (I was
                        in the mall looking for phone repair), and as it turns
                        out, See's Candy now charges a dollar -- a full dollar
                        -- for even the simplest of their wee confection
                        offerings. I bought two chocolate lollipops and two
                        chocolate-caramel-almond things. The total cost was
                        four-something. I mean, the candies were tasty and all,
                        but let's be real: A Snickers bar is fifty cents.
                        After this dollar-per-candy revelation, I may not
                        find myself wandering dreamily back into a See's
                        Candy any time soon.
                    </Typography>

                    <img src={img2} style={{height:'auto' , width:'80%'}} alt = "img1" />
                    <Typography paragraph>
                        Spending time at national parks can be an exciting
                        adventure, but this wasn't the type of excitement she was
                        hoping to experience. As she contemplated the situation
                        she found herself in, she knew she'd gotten herself in a
                        little more than she bargained for. It wasn't often that
                        she found herself in a tree staring down at a pack of
                        wolves that were looking to make her their next meal.
                    </Typography>
              </div>
            </div>

    );
}

The Hide tag hides the content under it up to certain breakpoints it has reached. In the above code, we have used to hide tag. So if the screen is smaller we want our drawer to hide. Also, we want to display some kind of button so that the user can click on it to open the drawer. So for toggling the drawer we need some kind of state which tells that whether the drawer is open or close and based on this we open or close the drawer. We are using React.useState() hook to define our drawer state.

So basically we are having to drawer wrapped inside the Hide tag. One of them will be shown and the other one will be hidden based on the screen size. The smUp props in the Hide tag says that if the screen size if 600px or more hide the content which is inside the tag or in other words if the screen is large enough make the drawer visible and permanent. Also in our classe.content property, we have specified:

    [theme.breakpoints.up('sm')]: {
         marginLeft: 300,
    },

which will leave 300px margin from left if the drawer on open and permanent so our content does not get hidden under the drawer. The xsDown props in the second Hide tag hide our permanent drawer or in other words, it will show our toggling drawer.

Responsive Drawer using materil ui

Sharing is caring!

Leave a Comment

Your email address will not be published. Required fields are marked *

shares
Scroll to Top