LoginSignup
0
1

はじめに

本記事では下記のようなシンプルなサイドバーを作成することを目的とします。

image.png

なお、レスポンシブルデザインにも対応するためにMaterial UIを活用します。
「サイドバー 作り方」の検索で出てくる記事・動画だと意外と実践的な内容が少ないため、参考になるかと思います。

作り方の全体像

フォルダ構成

Sidebar.jsとSidebarData.jsの二つのファイルを作成します。
image.png

Sidebar.jsではレスポンシブルなサイドバーの見た目を実装し、SidebarData.jsでは表示する項目(ホームやログイン)を表形式で管理します。

使い方

コンポーネントとして、いつでもSidebarが呼び出せる状態にして使います。

image.png

実装

事前準備

必要なライブラリをインストールします。エラーが出る場合はライブラリが足りない可能性があるため、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

表示項目は以下のようにディクショナリ型で管理します。

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に準備されているアイコンを活用します。下記のようにサイトからコードをコピーすればそのまま活用できます。
image.png

Material UIについての補足

Drawerは、Material-UIライブラリで提供されているコンポーネントの一つで、サイドバーやナビゲーションメニューを実装するために使用されます。Drawerは画面の端からスライドインするパネルで、通常はナビゲーションリンクや他の重要なコンテンツを含むために使われます。

Drawerの特徴

  1. スライドインパネル:
    画面の左側、右側、上部、または下部からスライドインすることができます。
  2. 常時表示または一時表示:
    永続的に表示する「permanent」モードや、必要に応じて表示する「temporary」モードがあります。
  3. レスポンシブ対応:
    画面サイズに応じて動作を変更でき、モバイルデバイスでは一時的なドロワーを使用し、デスクトップでは永続的なドロワーを使用することが一般的です。

まとめ

Sidebarをコンポーネントにして扱えるのはReactの強みだと思います。
再現性・汎用性を持たせるためにもMaterial UIはフル活用するのが良いと思います。

0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1