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

孤人 提交于 2020-07-09 06:53:32

问题


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>
        )   
}

回答1:


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:



来源:https://stackoverflow.com/questions/57749947/is-there-a-way-to-show-a-material-ui-drawer-nested-inside-a-grid-component

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!