Chakra UIのカスタムテーマ、使っていますか?
カスタムテーマは便利で汎用的なスタイルを定義することができますが、その反面で意外と奥が深くやろうとしていることに時間がかかってしまうこともあります。
今回はカスタムテーマをもっと使いこなすために基本〜深掘りしたところをまとめました。
- Chakra UIのカスタムテーマを使用する方法
- コンポーネントのカスタマイズ
- コンポーネント共通のスタイル定義
- グローバルなスタイル定義
- カスタムテーマ経由でのcssクラス名を対象にしたスタイル定義
前提
本記事ではChakra UI V2.7.0を対象としています。
これ以前のバージョンでは実装方法が異なることもあるので注意してください。
また実装ではTypeScriptを使用していますが必要に応じてJavaScriptに読み替えてください。
カスタムテーマとは?
Chakra UIではコンポーネントにスタイルをなにも指定しない場合でもデフォルトで適用されるスタイル(=デフォルトテーマ)があります。
カスタムテーマはこのデフォルトで適用されるスタイルそのものを変更したり、CSSのようにスタイルを上書きするためのものです。
説明だけではわかりにくいので実装を見ていきましょう。
カスタムテーマを使用しない場合
まずカスタムテーマを使用しない場合の実装例です。
1つめのボタンは個別にスタイルを指定していませんが、Chakra UIのデフォルトテーマが適用されているため単なる<button/>
とは異なりスタイルが適用された状態で表示されています。
2つめのボタンはProps(プロパティ)にて個別にスタイルを変更しています。
カスタムテーマを使用した場合
次にカスタムテーマを使用した場合の実装例です。
1つめのボタンはカスタムテーマを使用しない場合と同様に個別にスタイル指定していません。
しかし、先程の例とは異なるスタイルが適用されています。
これはデフォルトのスタイルをカスタムテーマにて変更したためです。
2つめのボタンはPropsで個別にスタイル指定することをやめ、カスタムテーマに定義したvariant
を使用して複数のスタイルをまとめて適用しています。
カスタムテーマでできること
上記を踏まえ改めてカスタムテーマでできることとしては、
- デフォルトテーマそのものを変更する
- CSSのように汎用的に使えるスタイルセットを定義して使い回せる
- 色・フォントサイズ・幅・高さ・ボーダーなどの基本的なスタイルを変更する
といった感じです。
カスタムテーマの始め方
とにもかくにもまずは実装してみましょう。
以下のステップで実際にカスタムテーマを適用してみてイメージを掴みたいと思います。
この時点では実装の詳細については触れませんので特に気にせずでOKです。
カスタムテーマ用のフォルダtheme
を作成します。
src/
`-- theme/
管理しやすくするためコンポーネント用フォルダtheme/components
を作成します。
src/
`-- theme/
`-- components/
theme/components/button.ts
を作成します。
export const Button = {
variants: {
base: {
bg: "green.300",
color: "white"
}
}
}
theme/index.ts
を作成します。
import { extendTheme } from "@chakra-ui/react"
import { Button } from "./components/button"
const customTheme = extendTheme({
components: {
Button
}
})
export default customTheme
Chakra UIを使用するためのChakraProvider
に上記カスタムテーマを渡します。
...中略
root.render(
<React.StrictMode>
<ChakraProvider theme={customTheme}>
<App />
</ChakraProvider>
</React.StrictMode>
)
今回はvariant
を定義しましたのでコンポーネントに設定する必要があります。
以下のようにButton
コンポーネントのProps
に渡してあげましょう。
<Button variant="base">test</Button>
上記を実際に実装したものは以下です。
カスタマイズの基本
ここからはカスタムテーマを使いこなすために必要なことをまとめていきます。
カスタムテーマの構造
カスタムテーマは以下のようにextendTheme
で定義した値を使用します。
import { extendTheme } from "@chakra-ui/react"
const customTheme = extendTheme({
components: {
Button: {
variants: {
base: {
bg: "green.300",
color: "white"
}
}
}
}
})
export default customTheme
上記の値をChakraProviderに渡すことでカスタムテーマが使用可能となります。
import { ChakraProvider } from "@chakra-ui/react"
import * as React from "react"
import { createRoot } from "react-dom/client"
import { App } from "./App"
import customTheme from "./theme"
const rootElement = document.getElementById("root")
const root = createRoot(rootElement)
root.render(
<React.StrictMode>
<ChakraProvider theme={customTheme}>
<App />
</ChakraProvider>
</React.StrictMode>
)
このようにextendTheme
の中にずらずらと定義を書いても動作上は問題ありません。
しかしカスタムテーマの始め方で示したようにファイル分割しておく方が管理しやすいです。
カスタマイズ可能な項目
カスタマイズ可能な項目(=extendTheme
内に定義できるもの)で主に使用するであろうものは以下です。
const theme = extendTheme({
components: {},
colors: {},
fonts: {},
sizes: {},
textStyles: {},
layerStyles: {},
shadows: {},
zIndices: {},
styles: {},
config: {},
})
他にもカスタマイズ可能なものはありますが基本的に上記で十分かと思います。
実際のカスタマイズ方法は以降で説明します。
コンポーネントの種類
Chakra UIが提供するコンポーネントは大きく以下の2つに分かれています。
- シングルパートコンポーネント(Single Part Components)
-
単一の要素のみで構成されているコンポーネント。
例えば
Button
はシングルパートコンポーネントです。 - マルチパートコンポーネント(Multipart Components)
-
複数の要素で構成されているコンポーネント。
例えば
Input
はマルチパートコンポーネントです。
コンポーネントの種類によってカスタムテーマの実装方法が異なります。
動作確認できないなどハマりがちなポイントなので注意です。
どのコンポーネントがどちらに該当するかは公式サイトのドキュメントもしくは公開されているソースコードから読み解く必要があります。
カスタマイズする(コンポーネント)
ここからはChakra UIが提供するコンポーネントをカスタマイズしてみます。
実装をみるのが一番わかりやすいためサンプル実装をベースに使い方をまとめます。
シングルパートコンポーネント(Single Part Components)
まずはシングルパートコンポーネントです。
ここではButton
コンポーネントを対象に実装します。
カスタマイズにはヘルパー関数defineStyleConfig
が補完がきいてオススメです。
設定できるプロパティは以下のようになります。
- baseStyle
-
対象コンポーネント全体に適用する基本スタイルを設定します。
上記の例では
borderRadius
を設定することでデフォルトの見た目を丸くしています。コンポーネントによって設定できるもの・できないものがあるので注意が必要です。
例えば
Button
の場合はbaseStyle
にbg
を設定して背景色を変更しようとしても反映されません。 - variants
-
対象コンポーネントで使用可能なスタイルのセットを定義します。
上記の例では黄色いボタンがわかりやすい使用例です。
使い方をまとめると、
- カスタムテーマ定義の
variants
に任意の名前のオブジェクト(例:attention
)を用意して適用したいスタイルをまとめて定義する。 - 個別のコンポーネント実装箇所の
variant
プロパティに①で定義したオブジェクトの名前(例:attention
)を指定する。
さまざまな種類のスタイルを
variant
の指定のみで汎用的に使い回せます。 - カスタムテーマ定義の
- sizes
-
対象コンポーネントのサイズを新たに定義できます。
上記の例では丸い大きめのボタンで使われています。
使い方はvariantsと同様に
- カスタムテーマ定義の
sizes
に任意の名前のオブジェクト(例:big
)を用意して適用したいスタイルをまとめて定義する。 - 個別のコンポーネント実装箇所の
size
プロパティに①で定義したオブジェクトの名前(例:big
)を指定する。
- カスタムテーマ定義の
- defaultProps
-
対象コンポーネントに適用するデフォルトのPropsを定義します。
上記例では
variant
に'base'
を指定しており、なにもPropsを与えないでButton
を表示した場合の見た目を'base'
で定義したスタイルとしています。
マルチパートコンポーネント(Multipart Components)
次にマルチパートコンポーネントです。
例としてCheckbox
を対象に実装します。
シングルパートコンポーネントと同じような感じですが、その対比としては
- 基本的な設定項目(
baseStyle
,variants
など)は同じ - コンポーネントを構成する複数の要素(上記実装では
control
,label
,icon
など)に対してスタイル定義する必要がある - 使用するヘルパー関数は
createMultiStyleConfigHelpers
,defineMultiStyleConfig
,definePartsStyle
の3つ
というようになります。
コンポーネントを構成する要素は公式ドキュメントのコンポーネントのページにて確認できるはずです。(コンポーネントによっては書いていない可能性もあるのでその場合はGithubやコード自動補完から調べる必要があります。)
例えばCheckbox
の構成要素を確認する場合は以下のドキュメントから確認できます。
カスタマイズする(共通スタイル)
前述のものは特定のコンポーネントを対象としたカスタマイズでした。
しかし共通の色やフォントなどを定義して使いまわしたい場合もあるかと思います。
Chakra UIのカスタムテーマではこのようなユースケースにも対応しています。
実装
共通スタイルにはさまざまなものを定義できます。
言葉にすると説明が難しい部分があるのでサンプル実装を見るのが早いです。
上記のサンプル実装以外にもさまざまなスタイルを定義できますが、今回はよく使うものに絞って実装してみました。
どんなものが使用できるかは公式ドキュメントの以下あたりが参考になります。
おすすめのフォルダ構造
カスタムテーマの始め方でも述べましたがカスタムテーマはどんどん肥大化していきます。
そのため公式でも推奨されている通りコード分割することが大事です。
ファイル/フォルダ構造としては以下のような構造がおすすめです。
theme/
|-- index.ts
|-- styles.ts
|-- components/
| |-- button.ts
| `-- checkbox.ts
`-- foundations/
|-- colors.ts
|-- fonts.ts
|-- textStyles.ts
|-- layerStyles.ts
`-- shadows.ts
コード分割を踏まえたサンプル実装は以下です。
最後に
Chakra UIはとても好きなライブラリのひとつです。
最近は公式ドキュメントが充実してきているので実装に困ることは減りましたが、それでも日本語情報が少なかったり、英語でも詳細な情報がなかったりすることもあります。
カスタムテーマもそのひとつなので本記事が実装の助けになれば幸いです。