目次
はじめに
この記事の概要
こんにちは、株式会社TOKOSのスギタです!
今回はtailwindcssを用いてUIライブラリMantineを使いハンバーガーメニューを作成する方法を説明していきたいと思います。
Maneineについてわからない方は下記を参考にしてください!
対象読者
- Reactを用いたWEB制作、WEB開発を行っている方
- tailwindcssを使用しながらUIライブラリを使用したい方
開発環境
- React 18.0.28
- Next.js13.2.3
- TypeScript 4.9.5
- Mantaine 6.0.13
- day.js 1.11.8
下記参照内でフレームワークを選択してください。
今回はNext.jsで行っていきたいと思います!
完成予定
今回の完成予定は下記になります。
ハンバーガーメニューの実装
まずはメニューボタンから作成します。
メニューボタンですが、MantineUIから、Burgerコンポーネントを使用します。
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 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>
}
Component 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>
}
Component propsのopenedをtrueに変えるとバツになると思います。
このComponent propsのopenedが表示状態の管理をしていることがわかったと思います。
ではこのメニューを押した際にopenedの真偽値を切り替えていきたいので、Component propsのonClickで押した際の動作を追記していきます。
また、今回は複数のコンポーネントの状態管理をuseDisclosureというMantineのCustomHooksを使用していきます。
import { Burger } from "@mantine/core"
import { useDisclosure } from "@mantine/hooks"
const ExamplePage: NextPageWithLayout = () => {
const [isHamburgerOpened,{ toggle: hamburgerToggle },] = useDisclosure(false)
<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に動作した関数によって切り替わった真偽値を渡すようにします。
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)
<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={true}
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から呼び出します。
ヘッダーより下にしたいので、Component propsのzIndexを0にします。
今回メニューを閉じるボタンはDrawerが行っているので、Component propsのwithCloseButtonはfalseにします(デフォルトがtrue)
Component propsのclaseNamesでデフォルトのpaddingを消し、メニューの幅を指定しています。
ここから、開く処理と閉じる処理を追記します。
import { Burger,Drawer } from "@mantine/core"
import { useDisclosure } from "@mantine/hooks"
const ExamplePage: NextPageWithLayout = () => {
const [isHamburgerOpened,{ close: hamburgerClose,toggle: hamburgerToggle },] = useDisclosure(false)
<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のHamburgerコンポーネントとDrawerコンポーネントそして、CustomHooksのuseDisclosureを使用しました。
やはりかなり簡単に実装できるかなと思いました。スクラッチで書こうとすると、overlayの箇所の動作や細かいアニメーションを考えるとかなり大変なので、こういう実装はUIライブラリに頼るのも手なのかなと感じます。