当サイトにもある、ハンバーガーメニューの実装について紹介します
この手の UI は広く知られ、実装方法とかいくらでもあると思いますが、当サイトの例を紹介します。
まずハンバーガーメニュー自体の描画です。
/**
* ハンバーガーメニューSVGのDOM
*/
const HamburgerMenuDOM = () => {
return (
<svg viewBox="0 0 24 24" className="h-6 w-6 fill-current">
<path
fillRule="evenodd"
clipRule="evenodd"
d="M3 18h18v-2H3v2zm0-5h18v-2H3v2zm0-7v2h18V6H3z"
></path>
</svg>
);
};
そしてサイドバー含めたヘッダー全体のコンポーネントです
export const Title = (title: string, path: string = "") => {
const [isOpen, setIsOpen] = useState(false);
useEffect(() => {
if (isOpen) {
document.body.style.overflow = "hidden";
} else {
document.body.style.overflow = "unset";
}
}, [isOpen]);
// 左サイドバーの領域
const LeftSideBar = (
links: {
url: string;
text: string;
}[],
isOpen: boolean
) => {
return (
<div
className={`transform top-0 left-0 w-64 fixed h-full overflow-auto ease-in-out transition-all duration-300 z-50 ${
isOpen ? "translate-x-0" : "-translate-x-full"
} bg-gray-700`}
>
<div className="flex flex-col space-y-2 p-4">
<div className="flex items-center pb-4">
<button
className="text-gray-500 hover:text-gray-50 focus:outline-none focus:text-gray-50 hover:bg-gray-800 rounded-full p-1"
aria-label="toggle menu"
onClick={() => setIsOpen(!isOpen)}
>
<HamburgerMenuDOM />
</button>
</div>
{links.map((link) => {
return (
<a
href={link.url}
className="text-gray-50 hover:underline transition duration-300 px-5 py-2 rounded-xl text-center hover:bg-gray-300 hover:text-gray-800"
key={link.url}
>
<span style={{ display: "inline-block" }}>{link.text}</span>
</a>
);
})}
</div>
</div>
);
};
return (
<>
<h2 className="text-center m-0 p-4 relative text-2xl font-bold shadow-lg flex bg-gray-800 text-gray-500">
<div className="flex items-center">
<button
className="text-gray-500 hover:text-gray-50 hover:bg-gray-900 focus:outline-none focus:text-gray-50 rounded-full p-1"
aria-label="toggle menu"
onClick={() => setIsOpen(!isOpen)}
>
<HamburgerMenuDOM />
</button>
</div>
<Link
href={path}
className="hover:text-gray-100 transition duration-300 ml-auto"
>
<span style={{ display: "inline-block" }}>{title}</span>
</Link>
</h2>
<div
className={`fixed inset-0 bg-black bg-opacity-50 z-50 transition-opacity ${
isOpen ? "opacity-100" : "opacity-0 pointer-events-none"
}`}
onClick={() => setIsOpen(false)}
></div>
{/* ハンバーガーメニュー押下時に表示される左サイドバー */}
{LeftSideBar(links, isOpen)}
</>
);
};
カスみたいなコードですね ❗️