目次
開発環境
- Visual Studio Code:version 1.73.0
- OS:Windows10
- Node.js:v18.14.0
- npm:9.3.1
- react:18.2.0
- react-dom:18.2.0
- react-router-dom:6.8.2
- typescript:4.9.5
- mui:5.11.10
- mui/icons-material:5.11.11
ヘッダーにMaterial UI(MUI)でハンバーガーメニューを実装する手順
ヘッダーにMaterial UI(MUI)でハンバーガーメニューを実装する手順を解説していきます。
Material UI(MUI)のアイコンをインストール
まずはMaterial UI(MUI)のアイコンをインストールします。
1 | npm install @mui/icons-material |
Material UI v5 では、アイコンの使用方法が以前のバージョンと異なっています。
以前のバージョンではSVG アイコンでしたが、v5からはFont Awesome アイコンが採用されており、必要なアイコンコンポーネントをインポートすることによってコンポーネント内で使用することができます。
ヘッダーのナビゲーションバーをレスポンシブにする
次にヘッダーのナビゲーションバーをレスポンシブにしていきます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 | import React from "react"; import { Link } from "react-router-dom"; import AppBar from "@mui/material/AppBar"; import Container from "@mui/material/Container"; import Box from "@mui/material/Box"; import List from "@mui/material/List"; import ListItem from "@mui/material/ListItem"; import ListItemButton from "@mui/material/ListItemButton"; import ListItemText from "@mui/material/ListItemText"; import Typography from "@mui/material/Typography"; import Logo from "../assets/images/logo.png" import MenuIcon from '@mui/icons-material/Menu'; const setNavLinks: Array<{ text: string, url: string }> = [ { text: "Top", url: "/" }, { text: "Profile", url: "/profile" }, { text: "Skill", url: "/skill" }, { text: "Production", url: "/production" }, { text: "Contact", url: "/contact" }, { text: "Blog", url: "/blog" }, ]; const Header: React.FC = () => { return( <> <AppBar component="header" position="static"> <Container maxWidth="md"> <Box sx={{ display: 'flex', justifyContent: 'space-between'}}> <Box> <Typography component="h1"> <Link to="/"> <img src={Logo} alt="Webエンジニアのポートフォリオサイト" height="60" width="auto" /> </Link> </Typography> </Box> <Box> <List component="nav" sx={{ display: 'flex', justifyContent: 'flex-start' }}> <ListItem disablePadding> <ListItemButton sx={{ textAlign: 'center', display: { xs: 'block', md: 'none' } }}> <ListItemText primary={<MenuIcon />} /> </ListItemButton> </ListItem> { setNavLinks.map( (navLink) => ( <ListItem disablePadding> <ListItemButton sx={{ textAlign: 'center', display: { xs: 'none', md: 'block' } }} component={Link} to={navLink.url}> <ListItemText primary={navLink.text} /> </ListItemButton> </ListItem> ))} </List> </Box> </Box> </Container> </AppBar> </> ); }; export default Header; |
まずはメニュー用のハンバーガーアイコンをインポートしておきます。
そしてハンバーガーメニューのボタンはmdサイズで非表示、xsサイズで表示されるようにdisplayのプロパティを割り当てていきます。
また、ナビゲーション部分に関しては逆にxsサイズで非表示、mdサイズで表示されるようにdisplayのプロパティを割り当てることにより、レスポンシブに切り替えることができます。
useStateによる状態管理をする
次にuseStateによる状態管理をするためのメソッドを定義していきます。
13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 | import MenuIcon from '@mui/icons-material/Menu'; import { useState } from "react"; const setNavLinks: Array<{ text: string, url: string }> = [ { text: "Top", url: "/" }, { text: "Profile", url: "/profile" }, { text: "Skill", url: "/skill" }, { text: "Production", url: "/production" }, { text: "Contact", url: "/contact" }, { text: "Blog", url: "/blog" }, ]; const Header: React.FC = () => { const [open, setOpen] = useState(false); const handleDrawerOpen = () => { setOpen(true); } const handleDrawerClose = () => { setOpen(false); } return( |
useStateをインポートしておきます。
「open,setOpen」という変数の初期値はfalseですが、handleDrawerOpenでは「setOpen」をtrue、handleDrawerCloseでは「setOpen」をfalseにすることにより、ハンバーガーメニューの開閉を管理します。
ハンバーガーメニューのドロワー部分を作成
次にハンバーガーメニューのドロワー部分を作成します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 | import React from "react"; import { Link } from "react-router-dom"; import AppBar from "@mui/material/AppBar"; import Container from "@mui/material/Container"; import Box from "@mui/material/Box"; import List from "@mui/material/List"; import ListItem from "@mui/material/ListItem"; import ListItemButton from "@mui/material/ListItemButton"; import ListItemText from "@mui/material/ListItemText"; import Typography from "@mui/material/Typography"; import Logo from "../assets/images/logo.png" import MenuIcon from '@mui/icons-material/Menu'; import CloseIcon from '@mui/icons-material/Close'; import { useState } from "react"; import Drawer from "@mui/material/Drawer"; const setNavLinks: Array<{ text: string, url: string }> = [ { text: "Top", url: "/" }, { text: "Profile", url: "/profile" }, { text: "Skill", url: "/skill" }, { text: "Production", url: "/production" }, { text: "Contact", url: "/contact" }, { text: "Blog", url: "/blog" }, ]; const Header: React.FC = () => { const [open, setOpen] = useState(false); const handleDrawerOpen = () => { setOpen(true); } const handleDrawerClose = () => { setOpen(false); } return( <> <AppBar component="header" position="static"> <Container maxWidth="md"> <Box sx={{ display: 'flex', justifyContent: 'space-between'}}> <Box> <Typography component="h1"> <Link to="/"> <img src={Logo} alt="Webエンジニアのポートフォリオサイト" height="60" width="auto" /> </Link> </Typography> </Box> <Box> <List component="nav" sx={{ display: 'flex', justifyContent: 'flex-start' }}> <ListItem disablePadding> <ListItemButton onClick={handleDrawerOpen} sx={{ textAlign: 'center', display: { xs: 'block', md: 'none' } }}> <ListItemText primary={<MenuIcon />} /> </ListItemButton> </ListItem> { setNavLinks.map( (navLink) => ( <ListItem disablePadding> <ListItemButton sx={{ textAlign: 'center', display: { xs: 'none', md: 'block' } }} component={Link} to={navLink.url}> <ListItemText primary={navLink.text} /> </ListItemButton> </ListItem> ))} </List> </Box> <Drawer anchor="right" open={open} onClose={handleDrawerClose} PaperProps={{ style: { width: '100%' } }}> <List component="nav" sx={{ display: 'block', justifyContent: 'normal' }}> <ListItem disablePadding> <ListItemButton onClick={handleDrawerClose} sx={{ textAlign: 'center', borderBottom: "solid 1px #696969" }}> <ListItemText primary={<CloseIcon />} /> </ListItemButton> </ListItem> { setNavLinks.map( (navLink) => ( <ListItem disablePadding> <ListItemButton onClick={handleDrawerClose} sx={{ textAlign: 'center', borderBottom: "solid 1px #696969" }} component={Link} to={navLink.url}> <ListItemText primary={navLink.text} /> </ListItemButton> </ListItem> ))} </List> </Drawer> </Box> </Container> </AppBar> </> ); }; export default Header; |
閉じるボタンのアイコンとMaterial UI(MUI)のDrawerをインポートします。
まずはクリックされたら「setOpne」がtureになるようクリックイベントにはhandleDrawerOpenを割り当てておきます。
そしてMaterial UI(MUI)のDrawer内にナビゲーション部分を作成し、クリックされたら「setOpne」がfalseになるようhandleDrawerCloseを割り当てておきます。
あとはDrawerのopenプロパティに割り当てたopenという変数がtrueとfalseで切り替わることにより、ドロワーの開閉を管理することができます。
おわりに
ReactでヘッダーにMaterial UI(MUI)でハンバーガーメニューを実装するための手順を解説してきましたが、いかがだったでしょうか。
サイト訪問者に気持ちよくサイトをみてもらにヘッダーのナビゲーションはとても重要であり、ナビゲーションのデザインや仕様にこだわっているエンジニアもかなり多いかと思います。
是非、魅力的なヘッダーのナビゲーションを作っていきましょう。