はじめに
お疲れ様です。りつです。
今回は、タイトルの通りChakra UI v3のトーストにまつわるtipsをご紹介します。
問題
Chakra UIの v1、v2まではトーストにisClosable
というオプションがあり、このオプションがtrue
だとトーストの閉じるボタンが表示されていたようです。
しかし、Chakra UI v3だとこのオプション自体がエラーになってしまい使用できませんでした。
どうにかして表示できないものかといろいろ試してみたところ、以下のように表示させることができたので、その方法をご紹介します。
解決方法
トーストの閉じるボタンを機能させるために以下を実施します。
- トーストの閉じる機能の有効化
- トーストの閉じるボタンを見やすく調整
1. トーストの閉じる機能の有効化
まず、トーストの閉じる機能を有効化する必要があります。
こちらは、toaster.create
に指定するオプションで、meta.closable
を設定します。
具体的には、以下のソースコードをご参照ください。
import { toaster } from "@/components/ui/toaster"
import { useCallback } from "react"
type Props = {
title: string;
type: "info" | "warning" | "success" | "error";
}
export const useMessage = () => {
const showMessage = useCallback((prpps: Props) => {
const { title, type } = prpps;
toaster.create({
title,
type,
duration: 2000,
+ meta: { closable: true } // トーストを閉じる処理を有効化
})
}, []);
return { showMessage }
}
【 参考 】showMessageの呼び出し元
import { useCallback, useState } from "react";
import { useNavigate } from "react-router";
import axios from "axios";
import { User } from "@/types/api/user";
import { useMessage } from "./useMessage";
export const useAuth = () => {
const navigate = useNavigate();
const { showMessage } = useMessage();
const [loading, setLoading] = useState(false);
const login = useCallback((id: string) => {
setLoading(true);
axios.get<User>(`https://jsonplaceholder.typicode.com/users/${id}`)
.then((res) => {
if (res.data) {
showMessage({ title: 'ログインしました', type: 'success' });
navigate('/home');
} else {
showMessage({ title: 'ユーザーが見つかりません', type: 'error' });
}
})
.catch(() => showMessage({ title: 'ログインできません', type: 'error' }))
.finally(() => setLoading(false));
}, [navigate, showMessage]);
return { login, loading };
};
【 参考 】Toasterコンポーネントの呼び出し元
import { Router } from '@/router/Router'
import { Toaster } from "@/components/ui/toaster"
function App() {
return (
<>
<Toaster />
<Router />
</>
)
}
export default App
2. トーストの閉じるボタンを見やすく調整
続いて、トーストの閉じるボタンのスタイルを調整します。
デフォルトだとなぜか閉じるボタンがほぼ目視できない上に、ものすごく小さく表示されておりクリックしずらく、視認性が悪いです。
そのため、src/components/ui/toaster.tsx
の<Toast.CloseTrigger/>
コンポーネントにスタイルを設定して、見やすく調整していきます。
上記ファイルは以下のコマンドを実行すると自動生成されます。
npx @chakra-ui/cli snippet add toaster
If you don't already have the snippet, run the following command to add the
toaster
snippet
"use client"
import {
Toaster as ChakraToaster,
Portal,
Spinner,
Stack,
Toast,
createToaster,
} from "@chakra-ui/react"
export const toaster = createToaster({
- placement: "bottom-end",
+ placement: "top", // 表示位置をページ上部に指定(ここの修正は任意でOKです)
pauseOnPageIdle: true
})
export const Toaster = () => {
return (
<Portal>
<ChakraToaster toaster={toaster} insetInline={{ mdDown: "4" }}>
{(toast) => (
<Toast.Root width={{ md: "sm" }}>
{toast.type === "loading" ? (
<Spinner size="sm" color="blue.solid" />
) : (
<Toast.Indicator />
)}
<Stack gap="1" flex="1" maxWidth="100%">
{toast.title && <Toast.Title>{toast.title}</Toast.Title>}
{toast.description && (
<Toast.Description>{toast.description}</Toast.Description>
)}
</Stack>
{toast.action && (
<Toast.ActionTrigger>{toast.action.label}</Toast.ActionTrigger>
)}
- {toast.meta?.closable && <Toast.CloseTrigger/>}
+ {toast.meta?.closable &&
+ <Toast.CloseTrigger
+ style={{width:'25px', height:'25px', color: 'white'}}
+ _hover={{ cursor: 'pointer' }}/>
+ } {/* Toast.CloseTriggerに対してスタイルを設定 */}
</Toast.Root>
)}
</ChakraToaster>
</Portal>
)
}
以上の手順で、トーストの閉じるボタンを表示・機能させることができます。
おわりに
今回は調べても情報がなかなか得られませんでした。
ソースコードを辿って推測しながら動かしてみた結果、トーストの閉じるボタンを機能させることができました。
もっと適切な方法があるかもしれませんので、ご存じの方がいたらぜひ教えてください。
参考