
【React】MantineUIで作るハンバーガーメニュー
はじめに
この記事の概要
こんにちは、株式会社TOKOSのスギタです!
今回はTailwind CSSを用いてUIライブラリMantineを使いハンバーガーメニューを作成する方法を説明していきたいと思います。
Mantineについてわからない方は下記を参考にしてください!
対象読者
- Reactを用いたWEB制作、WEB開発を行っている方
- Tailwind CSSを使用しながらUIライブラリを使用したい方
開発環境
react: 18.0.28next.js: 13.2.3typescript: 4.9.5@mantine/core: 6.0.13@mantine/hooks: 6.0.13
下記のリンク先でフレームワークを選択してください。
今回はNext.jsで行っていきたいと思います!
https://mantine.dev/pages/getting-started/
mantine.dev完成予定
今回の完成予定は下記になります。
ハンバーガーメニューの実装
まずはメニューボタンから作成します。
メニューボタンですが、MantineUIからBurgerコンポーネントを使用します。
Burger | Mantine
Open/close navigation button
mantine.devimport { Burger } from "@mantine/core"
const ExamplePage: NextPageWithLayout = () => (
<header className="fixed z-20 flex w-full gap-y-2 bg-blue-500 p-4 text-white shadow">
<div className="flex w-full max-w-[1366px] justify-between">
<div className="flex w-full justify-between">
<div>
<Burger opened={false} color="#fff" />
</div>
<p className="flex w-full items-center justify-center text-xl font-bold">TOKOS.inc</p>
</div>
</div>
</header>
)propsのcolorで色の指定をしています。
まだ状態管理をしていないので、現状は動かないと思います。
ではここから状態管理を追加して、メニューを押した際のアニメーションを追加していきたいと思います。
import { Burger } from "@mantine/core"
const ExamplePage: NextPageWithLayout = () => (
<header className="fixed z-20 flex w-full gap-y-2 bg-blue-500 p-4 text-white shadow">
<div className="flex w-full justify-between">
<div className="flex w-full justify-between">
<div>
<Burger opened={true} color="#fff" />
</div>
<p className="flex w-full items-center justify-center text-xl font-bold">TOKOS.inc</p>
</div>
</div>
</header>
)propsのopenedをtrueに変えるとバツになると思います。
このpropsのopenedが表示状態の管理をしていることがわかったと思います。
ではこのメニューを押した際にopenedの真偽値を切り替えていきたいので、propsのonClickで押した際の動作を追記していきます。
また、今回は複数のコンポーネントの状態管理にuseDisclosureというMantineのCustom Hooksを使用していきます。
use-disclosure | Mantine
Manages boolean state, provides open, close and toggle handlers, usually used with modals, drawers and popovers
mantine.devimport { Burger } from "@mantine/core"
import { useDisclosure } from "@mantine/hooks"
const ExamplePage: NextPageWithLayout = () => {
const [isHamburgerOpened, { toggle: hamburgerToggle }] = useDisclosure(false)
return (
<header className="fixed z-20 flex w-full gap-y-2 bg-blue-500 p-4 text-white shadow">
<div className="flex w-full justify-between">
<div className="flex w-full justify-between">
<div>
<Burger opened={isHamburgerOpened} onClick={hamburgerToggle} color="#fff" />
</div>
<p className="flex w-full items-center justify-center text-xl font-bold">TOKOS.inc</p>
</div>
</div>
</header>
)
}BurgerコンポーネントのonClickにuseDisclosureのtoggle関数(hamburgerToggle)を渡します。
またopenedに、toggle関数によって切り替わった真偽値を渡すようにします。
CustomHooksのuseDisclosureですが、公式ドキュメントを見ると、真偽値の管理、open、close、toggleのハンドラーとonOpenとonCloseのコールバックがあります。
今回はコールバック関数は使用しません。
// 公式のハンドラーの説明より
import { useDisclosure } from "@mantine/hooks"
function Demo() {
const [opened, handlers] = useDisclosure(false)
// openedをtrueに
handlers.open()
// openedをfalseに
handlers.close()
// openedの真偽値を反転
handlers.toggle()
}今回は、押した時にtoggle関数(hamburgerToggle)を使用して、真偽値の反転をしています。
初期値はメニューが閉じた状態にしたいので、falseにしています。
これで、メニューボタンの実装は完了です。
次にMantineUIのDrawerコンポーネントを使用して、メニューの実装をします。
import { Burger, Drawer } from "@mantine/core"
import { useDisclosure } from "@mantine/hooks"
const ExamplePage: NextPageWithLayout = () => {
const [isHamburgerOpened, { toggle: hamburgerToggle }] = useDisclosure(false)
return (
<header className="fixed z-20 flex w-full gap-y-2 bg-blue-500 p-4 text-white shadow">
<div className="flex w-full justify-between">
<div className="flex w-full justify-between">
<div>
<Burger opened={isHamburgerOpened} onClick={hamburgerToggle} color="#fff" />
<Drawer
opened={isHamburgerOpened}
zIndex={0}
withCloseButton={false}
classNames={{
body: "p-0",
inner: "w-[380px]",
}}
>
<div className="px-4 pt-[78px] font-bold">
<p className="mb-4">マイページ</p>
<p className="mb-4">ログアウト</p>
<p>ホーム</p>
</div>
</Drawer>
</div>
<p className="flex w-full items-center justify-center text-xl font-bold">TOKOS.inc</p>
</div>
</div>
</header>
)
}まずはDrawerコンポーネントを@mantine/coreから呼び出します。
ヘッダーより下にしたいので、propsのzIndexを0にします。
今回メニューの開閉はBurgerボタンで行うので、propsのwithCloseButtonはfalseにします(デフォルトがtrue)。
propsのclassNamesでデフォルトのpaddingを消し、メニューの幅を指定しています。
ここから、開く処理と閉じる処理を追記します。
import { Burger, Drawer } from "@mantine/core"
import { useDisclosure } from "@mantine/hooks"
const ExamplePage: NextPageWithLayout = () => {
const [isHamburgerOpened, { close: hamburgerClose, toggle: hamburgerToggle }] = useDisclosure(false)
return (
<header className="fixed z-20 flex w-full gap-y-2 bg-blue-500 p-4 text-white shadow">
<div className="flex w-full justify-between">
<div className="flex w-full justify-between">
<div>
<Burger opened={isHamburgerOpened} onClick={hamburgerToggle} color="#fff" />
<Drawer
opened={isHamburgerOpened}
onClose={hamburgerClose}
zIndex={0}
withCloseButton={false}
classNames={{
body: "p-0",
inner: "w-[380px]",
}}
>
<div className="px-4 pt-[78px] font-bold">
<p className="mb-4">マイページ</p>
<p className="mb-4">ログアウト</p>
<p>ホーム</p>
</div>
</Drawer>
</div>
<p className="flex w-full items-center justify-center text-xl font-bold">TOKOS.inc</p>
</div>
</div>
</header>
)
}useDisclosureにcloseハンドラーを追記し、openedで管理されている真偽値を渡します。
Drawerが閉じる際に発火する関数としてuseDisclosureのcloseハンドラーを渡します。
そうすることにより、メニューが開く際にisHamburgerOpenedがtrue、メニューが閉じた際にisHamburgerOpenedがfalseになるという切り替えが可能になります。
さいごに
今回はMantineのBurgerコンポーネントとDrawerコンポーネント、そしてCustomHooksのuseDisclosureを使用しました。
やはりかなり簡単に実装できるかなと思いました。
スクラッチで書こうとすると、overlayの箇所の動作や細かいアニメーションを考えるとかなり大変なので、こういう実装はUIライブラリに頼るのも手なのかなと感じます。




