Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there a way to show a Material-UI Drawer nested inside a Grid component?

I'm creating a web application using Material-UI. The main page is divided in 3 grids, each with a height of 500px. I wanted to display a drawer with some options of actions inside the middle grid. Is that possible? The way I have it so far I can only display it in relation to the whole screen.

Here's my main component with the grid elements:

import React, { Fragment } from 'react';
import Grid from '@material-ui/core/Grid';
import Paper from '@material-ui/core/Paper';

const style = {
    Paper: {
        padding: 10,
        marginTop: 5,
        marginBottom: 5,
        height: 500,
        overflowY: 'auto',
        position: 'relative',
    },
    Fab: {
        position: 'absolute',
        top: 5,
        left: 5
    },
}

export default () => {
    return (
        <Fragment>
            <Grid container spacing={1}>
                <Grid item xs={12} sm={4} md={4} lg={2}>
                    <Paper style={style.Paper}>

                    </Paper>
                </Grid>

                <Grid item xs={12} sm={8} md={8} lg={4}>
                    <Paper style={style.Paper}>
                        <ToolbarDrawer />
                    </Paper>
                </Grid>

                <Grid item xs={12} sm={12} md={12} lg={6}>
                    <Paper style={style.Paper}>

                    </Paper>
                </Grid>
            </Grid>
        </Fragment>
    );
}

Here's my drawer component which I would like to be displayed nested inside the middle grid:

javascript

import React, { Fragment } from 'react';
import IconButton from '@material-ui/core/IconButton';
import ChevronRightIcon from '@material-ui/icons/ChevronRight';
import ChevronLeftIcon from '@material-ui/icons/ChevronLeft';
import InboxIcon from '@material-ui/icons/MoveToInbox';
import MailIcon from '@material-ui/icons/Mail';
import { makeStyles } from '@material-ui/core/styles';
import clsx from 'clsx';
import Drawer from '@material-ui/core/Drawer';
import Divider from '@material-ui/core/Divider';
import ListItem from '@material-ui/core/ListItem';
import ListItemIcon from '@material-ui/core/ListItemIcon';
import ListItemText from '@material-ui/core/ListItemText';
import List from '@material-ui/core/List';
import CssBaseline from '@material-ui/core/CssBaseline';

const drawerWidth = 240;

const useStyles = makeStyles(theme => ({
  drawer: {
    width: drawerWidth,
    flexShrink: 0,
    whiteSpace: 'nowrap',
  },
  drawerOpen: {
    width: drawerWidth,
    transition: theme.transitions.create('width', {
      easing: theme.transitions.easing.sharp,
      duration: theme.transitions.duration.enteringScreen,
    }),
  },
  drawerClose: {
    transition: theme.transitions.create('width', {
      easing: theme.transitions.easing.sharp,
      duration: theme.transitions.duration.leavingScreen,
    }),
    overflowX: 'hidden',
    width: theme.spacing(6) + 1,
    [theme.breakpoints.up('sm')]: {
      width: theme.spacing(7) + 1,
    },
  },
  toolbar: {
    display: 'flex',
    alignItems: 'center',
    justifyContent: 'flex-end',
    padding: theme.spacing(0, 1),
    ...theme.mixins.toolbar,
  }
}));

export default () => {
    const classes = useStyles();

    const [open, setOpen] = React.useState(false);

    function handleToolbarClose() {
        setOpen(!open);
    }

    return (
            <Fragment>
                <CssBaseline />
                <Drawer
                    anchor="right"
                    variant="permanent"
                    className={clsx(classes.drawer, {
                      [classes.drawerOpen]: open,
                      [classes.drawerClose]: !open,
                    })}
                    classes={{
                      paper: clsx({
                        [classes.drawerOpen]: open,
                        [classes.drawerClose]: !open,
                      }),
                    }}
                    open={open}
                >
                    <div className={classes.toolbar}>
                      <IconButton onClick={handleToolbarClose}>
                        {(open) ? <ChevronRightIcon /> : <ChevronLeftIcon />}
                      </IconButton>
                    </div>
                    <Divider />
                    <List>
                      {['Inbox', 'Starred', 'Send email', 'Drafts'].map((text, index) => (
                        <ListItem button key={text}>
                          <ListItemIcon>{index % 2 === 0 ? <InboxIcon /> : <MailIcon />}</ListItemIcon>
                          <ListItemText primary={text} />
                        </ListItem>
                      ))}
                    </List>
                    <Divider />
                    <List>
                      {['All mail', 'Trash', 'Spam'].map((text, index) => (
                        <ListItem button key={text}>
                          <ListItemIcon>{index % 2 === 0 ? <InboxIcon /> : <MailIcon />}</ListItemIcon>
                          <ListItemText primary={text} />
                        </ListItem>
                      ))}
                    </List>
                </Drawer>

            </Fragment>
        )   
}
like image 805
makrottk Avatar asked Sep 01 '19 22:09

makrottk


People also ask

What is SM in material UI grid?

xs, extra-small: 0px. sm, small: 600px. md, medium: 900px. lg, large: 1200px.

How do you put a space between two grids in material UI?

The spacing property is an integer between 0 and 10 inclusive. By default, the spacing between two grid items follows a linear function: output(spacing) = spacing * 8px, e.g. spacing={2} creates a 16px wide gap.

What is grid in react?

DevExtreme React Grid is a component that displays table data from a local or remote source. It supports paging, sorting, filtering, grouping and other data shaping options, row selection, and data editing.

What is MUI grid?

The Material Design responsive layout grid adapts to screen size and orientation, ensuring consistency across layouts. The grid creates visual consistency between layouts while allowing flexibility across a wide variety of designs. Material Design's responsive UI is based on a 12-column grid layout. Feedback.


1 Answers

It looks like you're going to have to build a makeshift drawer component for this. Here is an example you could use to get started:

Live demo can be found here

MakeshiftDrawer using List component and Slide transition component:

export default function MakeshiftDrawer({ open }) {
  const classes = useStyles();
  const [selectedIndex, setSelectedIndex] = React.useState(1);

  function handleListItemClick(event, index) {
    setSelectedIndex(index);
  }

  return (
    <Slide direction="right" in={open} mountOnEnter unmountOnExit>
      <div className={classes.root}>
        <List component="nav" aria-label="main mailbox folders">
          <ListItem
            button
            selected={selectedIndex === 0}
            onClick={event => handleListItemClick(event, 0)}
          >
            <ListItemIcon>
              <InboxIcon />
            </ListItemIcon>
            <ListItemText primary="Inbox" />
          </ListItem>
          <ListItem
            button
            selected={selectedIndex === 1}
            onClick={event => handleListItemClick(event, 1)}
          >
            <ListItemIcon>
              <DraftsIcon />
            </ListItemIcon>
            <ListItemText primary="Drafts" />
          </ListItem>
        </List>
        <Divider />
        <List component="nav" aria-label="secondary mailbox folder">
          <ListItem
            button
            selected={selectedIndex === 2}
            onClick={event => handleListItemClick(event, 2)}
          >
            <ListItemText primary="Trash" />
          </ListItem>
          <ListItem
            button
            selected={selectedIndex === 3}
            onClick={event => handleListItemClick(event, 3)}
          >
            <ListItemText primary="Spam" />
          </ListItem>
        </List>
      </div>
    </Slide>
  );
}

MakeshiftDrawer in use:

function App() {
  const [isOpen, setIsOpen] = useState(true);

  const toggle = () => {
    setIsOpen(!isOpen);
  }

  return (
    <div>
      <Grid container direction="row" style={topGridStyle}>
      </Grid>
      <Grid container direction="row" style={midGridStyle}>
        <Grid item>
          <Button variant="contained" color="primary" onClick={toggle}>Toggle</Button>
          <MakeshiftDrawer open={isOpen} />
        </Grid>
      </Grid>
      <Grid container direction="row" style={botGridStyle}>
      </Grid>
    </div>
  );
}

Rendered:

enter image description here

like image 89
Matt Oestreich Avatar answered Oct 25 '22 18:10

Matt Oestreich