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

スポンサーリンク

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

動作イメージ

参考情報

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

React Drawer component - Material UI
Navigation drawers provide access to destinations in your app. Side sheets are surfaces containing supplementary content that are anchored to the left or right ...
React Drawer component - Material UI
Navigation drawers provide access to destinations in your app. Side sheets are surfaces containing supplementary content that are anchored to the left or right ...

実装コード

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

実装のポイントは、”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 アプリケーションです。参考にして下さい。

コメント

タイトルとURLをコピーしました