MUI React

React: MUI AppBar と Drawer を組み合わせた開閉メニューの作成 (サンプルあり)

2022年5月2日

React TypeScript アプリケーションに、MUI AppBar と Drawer コンポーネントを組み合わせて、開閉可能メニューを作成していきます。Drawer 開閉時に、App Bar に被らないサンプルとなっています。

※ useContext を利用して、Drawer コンポーネントの開閉状態を保持する方法は、次の記事で紹介しています。

動作イメージ

参考情報

サンプル作成時に参考にしたドキュメンテーションと実装コードは、下記二つです。

https://mui.com/material-ui/react-drawer/#clipped-under-the-app-bar
https://mui.com/material-ui/react-drawer/#persistent-drawer

実装コード

下記が、実装コードとなります。

実装のポイントは、"Main" styled コンポーネントのマージンを、アニメーション効果を加えて変化させているところです。(この辺りは、Drawer コンポーネント単体で作り切りたいところではありますが、現状実現方法が不明です。)

// 参考:https://mui.com/material-ui/react-drawer/#persistent-drawer
const Main = styled("main", { shouldForwardProp: (prop) => prop !== "open" })<{
  open?: boolean;
}>(({ theme, open }) => ({
  flexGrow: 1,
  padding: theme.spacing(3),
  transition: theme.transitions.create("margin", {
    easing: theme.transitions.easing.easeIn,
    duration: theme.transitions.duration.leavingScreen,
  }),
  marginLeft: -250,
  ...(open && {
    transition: theme.transitions.create("margin", {
      easing: theme.transitions.easing.easeOut,
      duration: theme.transitions.duration.enteringScreen,
    }),
    marginLeft: 0,
  }),
}));

function App() {
  const [isOpen, setOpenState] = React.useState<boolean>(true);
  const toggleOpenState = (): void => {
    setOpenState(!isOpen);
  };
  return (
    <Box sx={{ display: "flex" }}>
      <CssBaseline />
      {/* AppBar */}
      <Box sx={{ display: "flex" }}>
        <AppBar
          position="fixed"
          sx={{ zIndex: (theme) => theme.zIndex.drawer + 1 }}
        >
          <Toolbar>
            <IconButton
              color="inherit"
              aria-label="open drawer"
              edge="end"
              onClick={toggleOpenState}
              sx={{ mr: 2 }}
            >
              <MenuIcon />
            </IconButton>
            <Typography
              variant="h6"
              noWrap
              component="div"
              sx={{ display: "block" }}
            >
              タイトル
            </Typography>
          </Toolbar>
        </AppBar>
      </Box>
      {/* AppBar */}

      {/* Drawer */}
      {/* 参考:https://mui.com/material-ui/react-drawer/#clipped-under-the-app-bar */}
      <Drawer
        sx={{
          width: 250,
          flexShrink: 0,
          "& .MuiDrawer-paper": {
            width: 250,
          },
        }}
        variant="persistent"
        anchor="left"
        open={isOpen}
      >
        <Toolbar />
        <Box sx={{ overflow: "auto" }}>
          <List>
            <ListItem button>
              <ListItemText primary="メニュー1" />
            </ListItem>
            <ListItem button>
              <ListItemText primary="メニュー2" />
            </ListItem>
          </List>
        </Box>
      </Drawer>
      {/* Drawer */}

      {/* Main */}
      {/* 参考:https://mui.com/material-ui/react-drawer/#persistent-drawer */}
      <Main open={isOpen}>
        <Toolbar />
        <div>メイン</div>
      </Main>
      {/* Main */}
    </Box>
  );
}

export default App;

サンプルアプリケーション

TypeScript ベースの React アプリケーションです。参考にして下さい。

-MUI, React