はじめに
Chakra UIでのアイコンとモーダルの実装方法がv2以前とv3で大きく変化したようです。
参考にしていた動画教材はv2以前がベースであり、今回はv3でアイコンとモーダルを実装した時の方法を備忘録代わりに書いていこうと思います。
想定する実装内容
- モーダルを開閉するボタンを作成し、ハンバーガーのアイコンを設置する
┗ボタンの背景色は周囲の色と同化させる - ボタンを押下したらドロワーが開くようにする
- ×ボタンをドロワー内に設置し、押下するとドロワーが閉じるようにする
①v3以降のアイコンの実装方法
公式ドキュメント
Removed @chakra-ui/icons package. Prefer to use lucide-react or react-icons instead.
v3では@chakra-ui/icons
が使えないためlucide-react
もしくはreact-icons
を使います。
今回はreact-icons
を使うパターンを想定します。
実装方法
React Iconsの公式ページにアクセスし、お目当てのアイコンを探してインストール+インポートします。今回はFaBars
というアイコンを使います。
npm install react-icons --save
アイコンは単体で使うのではなくボタン化させたいので、Chakra UIのIcon Button
で囲むことでボタン化します。
この部分はv2以前の方法と変化ありません。
import { Flex, Heading, Link, Box, IconButton } from "@chakra-ui/react";
import { FC, memo } from "react";
import { FaBars } from "react-icons/fa";
export const Header: FC = memo(() => {
return (
<>
<IconButton size="sm" variant="plain" aria-label="メニューボタン" display={{ base: "block", md: "none" }}>
<FaBars color="white" />
</IconButton>
</>
);
});
※v3ではボタンの背景色を透明にしたい場合はvariant="plain"
で実装します。公式ドキュメントの下の方に説明がありました。
②v3以降のドロワーの実装方法
公式ドキュメント
実装方法
v3でもDrawer
を用いてドロワーを実装する点は一致していますが、コンポーネントの内部構造が変化しています。
公式のExampleには次のコードが記載されています。
<Drawer.Root>
<Drawer.Backdrop />
<Drawer.Trigger />
<Drawer.Positioner>
<Drawer.Content>
<Drawer.CloseTrigger />
<Drawer.Header>
<Drawer.Title />
</Drawer.Header>
<Drawer.Body />
<Drawer.Footer />
</Drawer.Content>
</Drawer.Positioner>
</Drawer.Root>
この中で特に実装において重要な部分を抜き出すと以下の部分になると思います。
-
<Drawer.Root>
:ドロワーの一番外側の部分。この部分にサイズや出現位置のプロパティを記載する。 -
<Drawer.Trigger />
:ドロワーを開く際のトリガー。入れ子にした内側に開くボタンとして扱いたいコンポーネントを記述する。 -
<Drawer.Content>
:ドロワーの内側の部分。いわゆるinner。 -
<Drawer.CloseTrigger />
:ドロワーの閉じるボタンのトリガー。入れ子にした内側に閉じるボタンとして扱いたいコンポーネントを記述する。 -
<Drawer.Header>
:ドロワーの上部(閉じるボタン付近)にあたる要素。titleなどを入れることが多い。 -
<Drawer.Body />
:モーダルのヘッダーとフッターで囲まれた部分。入れ子の内側はHTMLを書ける。 -
<Drawer.Footer />
:ドロワーの下部。主に「OK」「Cancel」などのボタンが入ることが多い。
以上をもとに実際に記述したコードは次のようになりました。
import { Flex, Heading, Link, Box, IconButton, Drawer, CloseButton } from "@chakra-ui/react";
import { FC, memo } from "react";
import { FaBars } from "react-icons/fa";
export const Header: FC = memo(() => {
return (
<>
<Flex as="nav" bg="teal.500" color="gray.50" align="center" justify="space-between" padding={{ base: 3, md: 5 }}>
<Flex align="center" as="a" mr={8} _hover={{ cursor: "pointer" }}>
<Heading as="h1" fontSize={{ base: "md", md: "lg" }}>
ユーザー管理アプリ
</Heading>
</Flex>
<Flex align="center" fontSize="sm" flexGrow={2} display={{ base: "none", md: "flex" }}>
<Box pr={4}>
<Link color="gray.50">ユーザー一覧</Link>
</Box>
<Link color="gray.50">設定</Link>
</Flex>
<Drawer.Root placement="start" size="xs">
<Drawer.Trigger asChild>
<IconButton size="sm" variant="plain" aria-label="メニューボタン" display={{ base: "block", md: "none" }}>
<FaBars color="white" />
</IconButton>
</Drawer.Trigger>
<Drawer.Backdrop />
<Drawer.Positioner>
<Drawer.Content>
<Drawer.Header>
<Drawer.Title />
</Drawer.Header>
<Drawer.Body>
<Button w="100%">TOP</Button>
<Button w="100%">ユーザー一覧</Button>
<Button w="100%">設定</Button>
</Drawer.Body>
<Drawer.Footer />
<Drawer.CloseTrigger asChild>
<CloseButton size="sm" />
</Drawer.CloseTrigger>
</Drawer.Content>
</Drawer.Positioner>
</Drawer.Root>
</Flex>
</>
);
});
ポイントとしてはHTML構成的に開くボタンを設置したい部分にDrawer
のコンポーネント群を設置することでした。
今回の例で言うと親要素の<Flex>
がヘッダー全体を囲う要素でありその中にハンバーガーボタンを配置したかったので、<Flex>
のモーダルの内側にDrawer
のコンポーネント群を設定しました。
また、<Drawer.Trigger asChild> </Drawer.Trigger>
で開くボタンにしたいコンポーネントを囲むことで、onClick
等のクリックイベントを記述しなくてもモーダルの開くボタンとして機能するようになります(closeButton
でも同様です)。
なお従来通りクリックイベントを関数化してボタンの開閉を制御することも可能のようです。詳しくは公式ドキュメントのControlled
のサンプルコードをご確認ください。
最後に
v3のドロワーの実装は一見難しそうに見える反面、開閉ボタンの構造などは使いやすくなっているように見えました。
この記事が参考になれば幸いです。
参考記事