はじめに
本記事では下記のようなシンプルなサイドバーを作成することを目的とします。
なお、レスポンシブルデザインにも対応するためにMaterial UIを活用します。
「サイドバー 作り方」の検索で出てくる記事・動画だと意外と実践的な内容が少ないため、参考になるかと思います。
作り方の全体像
フォルダ構成
Sidebar.jsとSidebarData.jsの二つのファイルを作成します。
Sidebar.jsではレスポンシブルなサイドバーの見た目を実装し、SidebarData.jsでは表示する項目(ホームやログイン)を表形式で管理します。
使い方
コンポーネントとして、いつでもSidebarが呼び出せる状態にして使います。
実装
事前準備
必要なライブラリをインストールします。エラーが出る場合はライブラリが足りない可能性があるため、ChatGPTにエラーを食わせて、足りないライブラリを教えてもらいご自身でnpm installして下さい。
npm install @mui/material @emotion/react @emotion/styled
Sidebar.js
スタイリング
- StyledDrawer: Drawerコンポーネントをカスタマイズして幅と背景色を設定
- StyledListItem: ListItemコンポーネントをカスタマイズして色とホバー時の背景色を設定
const StyledDrawer = styled(Drawer)(({ theme }) => ({
width: 250,
flexShrink: 0,
'& .MuiDrawer-paper': {
width: 250,
boxSizing: 'border-box',
background: '#2d445d',
},
}));
const StyledListItem = styled(ListItem)(({ theme }) => ({
color: 'white',
'&:hover': {
backgroundColor: '#3b627a',
},
}));
SidebarIconコンポーネント
- サイドバー上部に表示されるアイコンとテキストのリンクコンポーネント。
const SidebarIcon = () => (
<Link to="/" style={{ textDecoration: 'none', color: 'inherit' }}>
<Box display="flex" flexDirection="column" alignItems="center" py={2}>
<img src={Icon} alt="Icon" style={{ width: 100 }} />
<Typography variant="subtitle1" fontWeight={600} color="white">
FootBallApp
</Typography>
</Box>
</Link>
);
Sidebarコンポーネント
- theme, isMobile: Material-UIのテーマとメディアクエリを使用してレスポンシブデザインを実現
- mobileOpen: モバイルでのドロワーの開閉状態を管理するためのステート
- handleDrawerToggle: ドロワーの開閉をトグルする関数
- drawer: ドロワーの内容を定義。Toolbar、SidebarIcon、リンクのリストを含む
- IconButton: モバイルビューでのメニューボタン
- StyledDrawer: モバイルビューでは一時的なドロワー、デスクトップビューでは常に表示されるドロワー
このサイドバーは、レスポンシブデザインであり、モバイルとデスクトップの両方に対応しています。モバイルでは、メニューボタンをクリックするとドロワーが開閉します。デスクトップでは常に表示されます。
function Sidebar() {
const theme = useTheme();
const isMobile = useMediaQuery(theme.breakpoints.down('sm'));
const [mobileOpen, setMobileOpen] = React.useState(false);
const handleDrawerToggle = () => {
setMobileOpen(!mobileOpen);
};
const drawer = (
<>
<Toolbar />
<SidebarIcon />
<List>
{SidebarData.map((item, index) => (
<StyledListItem button component={Link} to={item.link} key={index}>
<ListItemIcon sx={{ color: 'white' }}>{item.icon}</ListItemIcon>
<ListItemText primary={item.title} />
</StyledListItem>
))}
</List>
</>
);
return (
<>
<IconButton
color="inherit"
aria-label="open drawer"
edge="start"
onClick={handleDrawerToggle}
sx={{ mr: 2, display: { sm: 'none' } }}
>
<MenuIcon />
</IconButton>
<StyledDrawer
variant={isMobile ? 'temporary' : 'permanent'}
open={isMobile ? mobileOpen : true}
onClose={handleDrawerToggle}
ModalProps={{ keepMounted: true }}
>
{drawer}
</StyledDrawer>
</>
);
}
SidebarData.js
表示項目は以下のようにディクショナリ型で管理します。
import React from 'react';
import HomeIcon from '@mui/icons-material/Home';
import LoginIcon from '@mui/icons-material/Login';
const SidebarData = [
{ title: "ホーム", icon: <HomeIcon />, link: "/" },
{ title: "ログイン", icon: <LoginIcon />, link: "/login" }
];
export default SidebarData;
表示しているアイコンについてはMUIに準備されているアイコンを活用します。下記のようにサイトからコードをコピーすればそのまま活用できます。
Material UIについての補足
Drawerは、Material-UIライブラリで提供されているコンポーネントの一つで、サイドバーやナビゲーションメニューを実装するために使用されます。Drawerは画面の端からスライドインするパネルで、通常はナビゲーションリンクや他の重要なコンテンツを含むために使われます。
Drawerの特徴
- スライドインパネル:
画面の左側、右側、上部、または下部からスライドインすることができます。 - 常時表示または一時表示:
永続的に表示する「permanent」モードや、必要に応じて表示する「temporary」モードがあります。 - レスポンシブ対応:
画面サイズに応じて動作を変更でき、モバイルデバイスでは一時的なドロワーを使用し、デスクトップでは永続的なドロワーを使用することが一般的です。
まとめ
Sidebarをコンポーネントにして扱えるのはReactの強みだと思います。
再現性・汎用性を持たせるためにもMaterial UIはフル活用するのが良いと思います。