はじめに
Webアプリでユーザー情報の変更などを行った際、処理が正常に完了したことをユーザーに伝えるために、画面の端に一時的にメッセージを表示する機能のことを「トースト」といいます。
トーストとは、主にデスクトップアプリケーションの機能で、情報通知用の小さなウィンドウをディスプレイの下方から一時的にポップアップ表示することである。
トーストを実装するのはそれほど難しくありませんが、プラグインも豊富に提供されているのでそれらを利用すると手軽に導入することができます。今回は、トースト機能を提供するReact-Toastifyというプラグインにおいて、PCの外観モードとトーストのカラーテーマを動的に連動させる方法について説明します。
PCの外観モードとトーストのテーマを連動させる
PCの外観モード
Macの場合、アップルメニュー > システム環境設定 > 一般メニューの中で外観モードを変更することができます。
CSSのprefers-color-scheme
を使うことで、Webデザインでも外観モードに合わせたカラーテーマを実装できるようになりました。最近はライトテーマ/ダークテーマ/外観モード準拠のいずれかからカラーテーマを選べるWebサイトが増えてきています。
最近人気のCSSフレームワークであるTailwind CSSでは、クラス名の先頭にdark:
をつけるだけで簡単にダークテーマを実装することができます。
React-Toastifyのカラーテーマ
React-Toastifyのカラーテーマはオプションで指定することができます。以下の例では、トーストのカラーテーマとしてdark
を指定しています(6行目)。カラーテーマはlight
dark
colored
のいずれかを指定することができます。
import { ToastContainer, toast } from 'react-toastify'
function App(){
const notify = () => {
toast("Wow so easy!", {
theme: "dark",
})
}
return (
<div>
<button onClick={notify}>Notify!</button>
<ToastContainer />
</div>
)
}
React-ToastifyのカラーテーマはPCの外観モードと連動しているわけではありません。例えば、Tailwind CSSなどを使ってWebサイト全体のカラーテーマをPCの外観モードと連動するようにしていても、React-Toastifyのトーストだけ異なるカラーテーマで表示されてしまう可能性があります。PCの外観モードをダークテーマに設定しており、Webサイトのカラーテーマも連動してダークテーマになっているのに、トーストのカラーテーマだけライトテーマになっていたりすると少し残念です。
React-Toastifyのカラーテーマを動的に設定
React-Toastifyのカラーテーマを動的に設定するには、まずJavaScriptの処理でPCの外観モードを確認します。
if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) {
// PCの外観モードはダークテーマに設定されている
}
この処理を使って、React-Toastifyのカラーテーマに設定する変数を用意します。
let mode = "light"
if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) {
mode = "dark"
}
用意した変数を使ってReact-Toastifyのカラーテーマを設定します。
let mode = "light"
if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) {
mode = "dark"
}
toast("Wow so easy!", {
theme: mode,
})
さて、JavaScriptであればこれだけで設定できたかと思います。しかし、TypeScriptだと次のような静的解析エラーが出ているはずです。
型 'string' を型 'Theme | undefined' に割り当てることはできません。ts(2322)
string
型のmode
変数をTheme | undefined
型のtheme
に設定することはできないというエラー内容です。実は、React-Toastifyのtheme
オプションはstring
型ではなくTheme
型というReact-Toastify内部で定義された型を使用しています。そのため、light
やdark
といった単なる文字列が入っているだけの変数を設定しようとすると静的解析エラーが発生するというわけです。
この静的解析エラーが出ていてもWebアプリが動かなくなるわけではありません。それどころか、React-Toastifyのトーストも表示されますし、ちゃんとPCの外観モードと連動したカラーテーマが設定されています。しかし、エラーが残っているのは気持ち悪いし、ちゃんと解決する方法があります。
React-Toastifyのカラーテーマに設定する変数の宣言時に、React-Toastifyのtheme
オプションで使用するTheme
型を指定します。
let mode: Theme = "light"
React-Toastifyのカラーテーマに設定する変数がTheme
型として定義されたため、上記の静的解析エラーは解消されました。しかし、今度は次のような静的解析エラーが出ているかと思います。
名前 'Theme' が見つかりません。ts(2304)
Theme
型はReact-Toastify内部で定義された型のため、型定義をインポートする必要があります。
import { ToastContainer, toast, Theme } from 'react-toastify'
これで静的解析エラーはすべて解消されたかと思います。動作確認し、トーストのカラーテーマがPCの外観モードと連動していることを確認してください。まとめると、以下のような実装になります。
import { ToastContainer, toast, Theme } from 'react-toastify'
function App(){
const notify = () => {
let mode: Theme = "light"
if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) {
mode = "dark"
}
toast("Wow so easy!", {
theme: mode,
})
}
return (
<div>
<button onClick={notify}>Notify!</button>
<ToastContainer />
</div>
)
}
まとめ
トースト機能を提供するReact-Toastifyというプラグインにおいて、PCの外観モードとトーストのカラーテーマを動的に連動させる方法について説明しました。この方法について検索してみたのですが、明確に解説している情報を見つけることはできませんでした。Stack Overflowで質問している人はいましたが、回答している人はいませんでした。
トースト機能があるとUXが向上し、Webアプリの利便性が向上します。トースト機能を実装するプラグインはいろいろありますが、React-Toastifyは簡単に導入でき、デザインに優れ、カスタマイズ性も高いので非常におすすめです。