アカウントメニューの作成
パッケージのインストール
frontend$ yarn add @mui/material
frontend$ yarn add @mui/icons-material
# ...(5分程度)...
frontend$ yarn add @emotion/react
frontend$ yarn add @emotion/styled
frontend$ less package.json
...(略)...
"dependencies": {
"@emotion/react": "^11.14.0", # <-
"@emotion/styled": "^11.14.0", # <-
"@mui/icons-material": "^7.0.1", # <-
"@mui/material": "^7.0.1", # <-
"next": "15.2.4",
"next-auth": "^5.0.0-beta.25",
"prettier": "^3.5.3",
"prettier-plugin-tailwindcss": "^0.6.11",
"react": "^19.0.0",
"react-dom": "^19.0.0"
},
...(略)...
アカウントメニュー
Material UIのAccount menuをベースにAccountMenu.tsx
を作成してください。
use clieant;
を追加する。- Hydration error回避の処理を追加する。
- 余分な項目を削除する。
frontend/src/app/components/ui/AccountMenu.tsx
'use client'; // <- 追加
import * as React from 'react';
import Box from '@mui/material/Box';
import Avatar from '@mui/material/Avatar';
import Menu from '@mui/material/Menu';
import MenuItem from '@mui/material/MenuItem';
import ListItemIcon from '@mui/material/ListItemIcon';
import Divider from '@mui/material/Divider';
import IconButton from '@mui/material/IconButton';
// import Typography from '@mui/material/Typography'; // <- 削除
import Tooltip from '@mui/material/Tooltip';
// import PersonAdd from '@mui/icons-material/PersonAdd'; // <- 削除
// import Settings from '@mui/icons-material/Settings'; // <- 削除
import Logout from '@mui/icons-material/Logout';
export default function AccountMenu() {
const [anchorEl, setAnchorEl] = React.useState<null | HTMLElement>(null);
const [isClient, setIsClient] = React.useState(false); // <- 追加
// ↓追加
// Hydration error回避のため、クライアントサイドのみで状態を設定する。
React.useEffect(() => {
setIsClient(true);
}, []);
// ↑追加
const open = Boolean(anchorEl);
const handleClick = (event: React.MouseEvent<HTMLElement>) => {
setAnchorEl(event.currentTarget);
};
const handleClose = () => {
setAnchorEl(null);
};
// ↓追加
// クライアントサイドでのみレンダリングする部分を分ける。
if (!isClient) {
return null; // サーバサイドでは何もレンダリングしない。
}
// ↑追加
return (
<React.Fragment>
<Box sx={{ display: 'flex', alignItems: 'center', textAlign: 'center' }}>
{/* ↓削除
<Typography sx={{ minWidth: 100 }}>Contact</Typography>
<Typography sx={{ minWidth: 100 }}>Profile</Typography>
↑削除 */}
<Tooltip title="Account settings">
<IconButton
onClick={handleClick}
size="small"
sx={{ ml: 2 }}
aria-controls={open ? 'account-menu' : undefined}
aria-haspopup="true"
aria-expanded={open ? 'true' : undefined}
>
<Avatar sx={{ width: 32, height: 32 }}>M</Avatar>
</IconButton>
</Tooltip>
</Box>
<Menu
anchorEl={anchorEl}
id="account-menu"
open={open}
onClose={handleClose}
onClick={handleClose}
slotProps={{
paper: {
elevation: 0,
sx: {
overflow: 'visible',
filter: 'drop-shadow(0px 2px 8px rgba(0,0,0,0.32))',
mt: 1.5,
'& .MuiAvatar-root': {
width: 32,
height: 32,
ml: -0.5,
mr: 1,
},
'&::before': {
content: '""',
display: 'block',
position: 'absolute',
top: 0,
right: 14,
width: 10,
height: 10,
bgcolor: 'background.paper',
transform: 'translateY(-50%) rotate(45deg)',
zIndex: 0,
},
},
},
}}
transformOrigin={{ horizontal: 'right', vertical: 'top' }}
anchorOrigin={{ horizontal: 'right', vertical: 'bottom' }}
>
{/* ↓削除
<MenuItem onClick={handleClose}>
<Avatar /> Profile
</MenuItem>
↑削除 */}
<MenuItem onClick={handleClose}>
<Avatar /> My account
</MenuItem>
<Divider />
{/* ↓削除
<MenuItem onClick={handleClose}>
<ListItemIcon>
<PersonAdd fontSize="small" />
</ListItemIcon>
Add another account
</MenuItem>
<MenuItem onClick={handleClose}>
<ListItemIcon>
<Settings fontSize="small" />
</ListItemIcon>
Settings
</MenuItem>
↑削除 */}
<MenuItem onClick={handleClose}>
<ListItemIcon>
<Logout fontSize="small" />
</ListItemIcon>
Logout
</MenuItem>
</Menu>
</React.Fragment>
);
}
ヘッダ
frontend/src/app/components/Header.tsx
import Link from 'next/link';
import React from 'react';
import AccountMenu from './ui/AccountMenu'; // <- 追加
const Header = () => {
return (
...(略)...
<nav className="flex items-center justify-between text-sm font-medium">
<div className="p-2">
<Link href="/about/">About</Link>
</div>
<div className="p-2">Sign In</div>
<AccountMenu /> {/* <- 追加 */}
</nav>
...(略)...
);
};
export default Header;
ブラウザで下記URLにアクセスし、ヘッダ右上のアイコンをクリックすると、アカウントメニューが表示されます。