テーマを切り替える
Yamada UIは、ユーザーがテーマを切り替える機能を提供しています。
この機能を有効にするには、複数のテーマを用意する必要があります。
セットアップ
ユーザーがテーマを切り替えるには、次の2つのことを行う必要があります。
- 複数のテーマを用意する
ThemeSchemeScript
をアプリケーションに追加する。
複数のテーマを用意する
今回は、デフォルトのテーマからカラーを変更したテーマを複数用意します。
テーマをカスタマイズする方法が分からない場合は、こちらをご覧ください。
themeSchemes
にオブジェクトを渡します。このオブジェクトのキーがテーマを切り替えるために必要なthemeScheme
になります。
themeSchemes
は、CSSの属性セレクター
を用いてカスタムプロパティ
をオーバーライドします。themeScheme
が切り替わるごとに対応する属性セレクター
内のカスタムプロパティ
が参照されます。
import { extendTheme } from "@yamada-ui/react"export const theme = extendTheme({themeSchemes: {pink: {semantics: {colors: { primary: "pink.500" },colorSchemes: { primary: "pink" },},},purple: {semantics: {colors: { primary: "purple.500" },colorSchemes: { primary: "purple" },},},green: {semantics: {colors: { primary: "green.500" },colorSchemes: { primary: "green" },},},},})()
もし、themeSchemes
で渡したテーマのいずれかをデフォルトで使用したい場合は、コンフィグのinitialThemeScheme
に初期値を設定します。
import { extendTheme, extendConfig } from "@yamada-ui/react"export const theme = extendTheme({themeSchemes: {pink: {semantics: {colors: { primary: "pink.500" },colorSchemes: { primary: "pink" },},},purple: {semantics: {colors: { primary: "purple.500" },colorSchemes: { primary: "purple" },},},green: {semantics: {colors: { primary: "green.500" },colorSchemes: { primary: "green" },},},},})()export const config = extendConfig({initialThemeScheme: "pink",})
ThemeSchemeScript
を追加する
テーマを正常に切り替えるには、head
やbody
内にThemeSchemeScript
を追加する必要があります。
理由は、テーマの切り替えがlocalStorage
やcookies
を用いて実装されており、ページの読み込み時に同期を正しく機能させるためです。
Create React Appの場合
index.tsx
import { createRoot } from "react-dom/client"import { App } from "./app"import { UIProvider, getThemeSchemeScript } from "@yamada-ui/react"import { theme, config } from "./theme"const injectThemeSchemeScript = () => {const scriptContent = getThemeSchemeScript({initialThemeScheme: config.initialThemeScheme,})const script = document.createElement("script")script.textContent = scriptContentdocument.head.appendChild(script)}injectThemeSchemeScript()const container = document.getElementById("app")const root = createRoot(container!)root.render(<UIProvider theme={theme} config={config}><App /></UIProvider>,)
props
のinitialThemeScheme
は、コンフィグと同じinitialThemeScheme
を渡してください。
Next.jsの場合
_document.tsx
import { Html, Head, Main, NextScript } from "next/document"import { ThemeSchemeScript } from "@yamada-ui/react"import { config } from "../theme"export default function Document() {return (<Html lang="en"><Head /><body><ThemeSchemeScript initialThemeScheme={config.initialThemeScheme} /><Main /><NextScript /></body></Html>)}
プロジェクトによっては、cookies
から値を取得する場合があるかもしれません。その場合は、createThemeSchemeManager("cookie")
を使用します。
_document.tsx
import { Html, Head, Main, NextScript } from "next/document"import { ThemeSchemeScript } from "@yamada-ui/react"import { config } from "../theme"export default function Document() {return (<Html lang="en"><Head /><body><ThemeSchemeScripttype="cookie"nonce="testing"initialThemeScheme={config.initialThemeScheme}/><Main /><NextScript /></body></Html>)}
_app.tsx
import type { AppProps } from "next/app"import { UIProvider, createThemeSchemeManager } from "@yamada-ui/react"import { config } from "../theme"const themeSchemeManager = createThemeSchemeManager("cookie")export default function App({ Component, pageProps }: AppProps) {return (<UIProvidertheme={theme}config={config}themeSchemeManager={themeSchemeManager}><Component {...pageProps} /></UIProvider>)}
props
のinitialThemeScheme
は、コンフィグと同じinitialThemeScheme
を渡してください。
themeSchemeManager
を追加する
Next.jsなどのサーバー側でレンダリングされるサイトの場合は、テーマがハイドレーション中に変更することを避けるために、リクエストにテーマのスキーマを含めたい場合があります。
サーバーサイドレンダリングを使用しない場合は、こちら手順をする必要はありません。Yamada UIは、デフォルトでlocalStorage
を使用しています。
getServerSideProps
を用意する
複数のページでgetServerSideProps
を共通化するために、getServerSideCommonProps
を定義します。
import { GetServerSidePropsContext } from "next"export const getServerSideCommonProps = ({req,}: GetServerSidePropsContext) => {return {props: {cookies: req.headers.cookie ?? "",},}}
themeSchemeManager
にcookies
を設定する
createThemeSchemeManager
にssr
とcookies
を設定します。
_app.tsx
import type { AppProps } from "next/app"import { UIProvider, createThemeSchemeManager } from "@yamada-ui/react"export default function App({ Component, pageProps }: AppProps) {const { cookies } = pagePropsconst themeSchemeManager = createThemeSchemeManager("ssr", cookies)return (<UIProvider themeSchemeManager={themeSchemeManager}><Component {...pageProps} /></UIProvider>)}
getServerSideProps
を追加する
先ほど作成したgetServerSideCommonProps
を各ページに追加します。
index.tsx
import { getServerSideCommonProps } from "../get-server-side-props.ts"import { Button } from "@yamada-ui/react"export default function Index() {return <Button>Click me!</Button>}export const getServerSideProps = getServerSideCommonProps
テーマを切り替える
テーマの切り替えには、changeThemeScheme
を使います。もしthemeScheme
を元に戻したい場合は、base
を渡します。
編集可能な例
const { themeScheme, changeThemeScheme } = useTheme() return ( <> <Text>The current scheme is "{themeScheme}"</Text> <Wrap mt="md" gap="md"> <Button onClick={() => changeThemeScheme("base")}>Base Theme</Button> <Button colorScheme="pink" onClick={() => changeThemeScheme("pink")}> Pink Theme </Button> <Button colorScheme="purple" onClick={() => changeThemeScheme("purple")}> Purple Theme </Button> <Button colorScheme="green" onClick={() => changeThemeScheme("green")}> Green Theme </Button> </Wrap> </> )
GitHubでこのページを編集する