Yamada UIにスターをあげる

スター
Yamada UIYamada UIv1.3.10

テーマを切り替える

Yamada UIは、ユーザーがテーマを切り替える機能を提供しています。

セットアップ

ユーザーがテーマを切り替えるには、次の2つのことを行う必要があります。

  1. 複数のテーマを用意する
  2. ThemeSchemeScriptをアプリケーションに追加する。

複数のテーマを用意する

今回は、デフォルトのテーマからカラーを変更したテーマを複数用意します。

themeSchemesにオブジェクトを渡します。このオブジェクトのキーがテーマを切り替えるために必要な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を追加する

テーマを正常に切り替えるには、headbody内にThemeSchemeScriptを追加する必要があります。

理由は、テーマの切り替えがlocalStoragecookiesを用いて実装されており、ページの読み込み時に同期を正しく機能させるためです。

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 = scriptContent
document.head.appendChild(script)
}
injectThemeSchemeScript()
const container = document.getElementById("app")
const root = createRoot(container!)
root.render(
<UIProvider theme={theme} config={config}>
<App />
</UIProvider>,
)

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>
<ThemeSchemeScript
type="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 (
<UIProvider
theme={theme}
config={config}
themeSchemeManager={themeSchemeManager}
>
<Component {...pageProps} />
</UIProvider>
)
}

themeSchemeManagerを追加する

Next.jsなどのサーバー側でレンダリングされるサイトの場合は、テーマがハイドレーション中に変更することを避けるために、リクエストにテーマのスキーマを含めたい場合があります。

getServerSidePropsを用意する

複数のページでgetServerSidePropsを共通化するために、getServerSideCommonPropsを定義します。

import { GetServerSidePropsContext } from "next"
export const getServerSideCommonProps = ({
req,
}: GetServerSidePropsContext) => {
return {
props: {
cookies: req.headers.cookie ?? "",
},
}
}

themeSchemeManagercookiesを設定する

createThemeSchemeManagerssrcookiesを設定します。

_app.tsx

import type { AppProps } from "next/app"
import { UIProvider, createThemeSchemeManager } from "@yamada-ui/react"
export default function App({ Component, pageProps }: AppProps) {
const { cookies } = pageProps
const 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でこのページを編集する

コンポーネントのスタイルコンフィグ