はじめに
こんにちは、H×Hのセンリツ大好きエンジニアです。(同担OKです😉)
今回は、2024年10月にメジャーアップデートされたChakra UIの変更点が思いの外多かったので、簡単にではありますがまとめました。
(足りない情報があればコメント等で教えていただけますと幸いです🙇)
この記事で取り上げる変更点
使用するパッケージ
V3では @emotion/styled
とframer-motion
パッケージが使用されません。
また、@chakra-ui/next-js
も不要になりました。(asChild
propsの登場により)
そのため、インストールするときは以下のコマンドでインストールします。
npm i @chakra-ui/react @emotion/react
V3ではCLIパッケージも新たに追加され、今まで使用していたコンポーネント(Accordion
やProgress
など)を使用する際には以下のコマンドから事前に定義されたスニペットとして追加できます。
npx @chakra-ui/cli snippet add
Theme、Recipe
Theme
Themeに関しても、Panda CSSを参考にして作られているため仕様が変わっています。
(Panda CSSを使っているような説明ですが、実際にはPanda CSSはChakra UIで使用されていません)
theme.ts
では今までextendTheme
を使用することで独自のスタイリングや、コンポーネント毎のプロパティ調整など行っていましたが、V3からはcreateSystem
とdefaultConfig
を使う必要があります。
import { createSystem, defaultConfig } from "@chakra-ui/react"
export const system = createSystem(defaultConfig, {
theme: {
tokens: {
fonts: {
heading: { value: `'Figtree', sans-serif` },
body: { value: `'Figtree', sans-serif` },
},
},
},
})
theme.ts
の中で設定できるプロパティの例としては、以下のものがあります。
- breakpoints: ブレークポイントを定義する
- keyframes: CSSキーフレームアニメーションを定義する
- tokens: トークンを定義する
- semanticTokens: セマンティックトークンを定義する
- textStyles: タイポグラフィスタイルを定義する
- layerStyles: レイヤースタイルを定義する
- animationStyles: アニメーションスタイルを定義する
- recipes: コンポーネントレシピを定義する
- slotRecipes: コンポーネントスロットレシピを定義する
この中にあるtokens
やsemanticTokens
は独自のカラーコードやフォントを設定するためのものです。
また、Themeの中で最も変わった部分としては、recipes
とslotRecipes
になるかと思います。
Recipe
Recipeは、ButtonやInputなどのコンポーネントのプロパティをグローバルに定義することが出来るものです。
以前はコンポーネント毎にdefineStyle
とdefineStyleConfig
を使用していましたが、Panda CSSライクになったことで廃止になりました。
使用方法としては、defineRecipe
を使用して独自のRecipeを作成します。
import { defineRecipe } from "@chakra-ui/react"
export const buttonRecipe = defineRecipe({
base: {
display: "flex",
},
variants: {
visual: {
solid: { bg: "red.200", color: "white" },
outline: { borderWidth: "1px", borderColor: "red.200" },
},
size: {
sm: { padding: "4", fontSize: "12px" },
lg: { padding: "8", fontSize: "24px" },
},
},
})
これをtheme.ts
内で既存のコンポーネントに適用します。
import { buttonRecipe } from "./button.recipe"
export const system = createSystem(defaultConfig, {
theme: {
tokens: {
fonts: {
heading: { value: `'Figtree', sans-serif` },
body: { value: `'Figtree', sans-serif` },
},
recipes: {
button: buttonRecipe,
},
},
},
})
ここで注意が必要なのですが、以前のようにvariant
を独自で設定した場合CLIでRecipeの型を生成してあげる必要があります。
これをしないと、型エラーが発生してしまいます。
npx @chakra-ui/cli typegen ./theme.ts
Button
やInput
などの単体で動作するコンポーネントに関してはRecipe
で定義できますが、Accordion
などの組み合わせることで初めて機能するコンポーネントに関してはSlotRecipe
で定義する必要があります。
ちなみに、Accordionは以下のような形になっています。(Ark UIを基に作成されているため)
import {
AccordionItem,
AccordionItemContent,
AccordionItemTrigger,
AccordionRoot,
} from "@/components/ui/accordion"
const Demo = () => {
return (
<AccordionRoot collapsible defaultValue={["b"]}>
{items.map((item, index) => (
<AccordionItem key={index} value={item.value}>
<AccordionItemTrigger>{item.title}</AccordionItemTrigger>
<AccordionItemContent>{item.text}</AccordionItemContent>
</AccordionItem>
))}
</AccordionRoot>
)
}
const items = [
{ value: "a", title: "First Item", text: "Some value 1..." },
{ value: "b", title: "Second Item", text: "Some value 2..." },
{ value: "c", title: "Third Item", text: "Some value 3..." },
]
SlotRecipe
も基本的にはRecipe
と同様に定義することが可能ですが、複数のパーツに分かれているためどこのパーツにプロパティを適用させるか決める必要があります。
以下の画像はArk UIの公式リファレンス内で確認できます。
現段階ではChakra UIのリファレンスに上記の画像が掲載されていないため、コンポーネント関連に関してはArk UIのリファレンスを見た方が良いです。
そのため、Accordionを例に挙げる場合はSlotRecipeを以下のようにパーツ毎で記述します。
import { defineRecipe } from "@chakra-ui/react"
export const accordionSlotRecipe = defineSlotRecipe({
slots: ["root", "item", "itemTrigger", "itemBody", "itemContent"],
base: {
root: {
width: "full",
"--accordion-radius": "radii.l2",
},
item: {
overflowAnchor: "none",
},
itemTrigger: {
display: "flex",
alignItems: "center",
width: "full",
outline: "0",
gap: "3",
fontWeight: "medium",
borderRadius: "var(--accordion-radius)",
_focusVisible: {
outline: "2px solid",
outlineColor: "colorPalette.focusRing",
},
_disabled: {
layerStyle: "disabled",
},
},
itemBody: {
pt: "var(--accordion-padding-y)",
pb: "calc(var(--accordion-padding-y) * 2)",
},
itemContent: {
overflow: "hidden",
borderRadius: "var(--accordion-radius)",
_open: {
animationName: "expand-height, fade-in",
animationDuration: "moderate",
},
_closed: {
animationName: "collapse-height, fade-out",
animationDuration: "moderate",
},
},
variants: {
variant: {
outline: {
item: {
borderBottomWidth: "1px",
},
},
},
},
})
上記のように、Chakra UIが事前に定義しているoutline
のようなvariantにも上書きでプロパティを変更できたりもします。
実際に適用する場合は、AccordionコンポーネントのRootにvariantを設定してあげます。
import {
AccordionItem,
AccordionItemContent,
AccordionItemTrigger,
AccordionRoot,
} from "@/components/ui/accordion"
const Demo = () => {
return (
<AccordionRoot collapsible defaultValue={["b"]} variant="outline">
{items.map((item, index) => (
<AccordionItem key={index} value={item.value}>
<AccordionItemTrigger>{item.title}</AccordionItemTrigger>
<AccordionItemContent>{item.text}</AccordionItemContent>
</AccordionItem>
))}
</AccordionRoot>
)
}
const items = [
{ value: "a", title: "First Item", text: "Some value 1..." },
{ value: "b", title: "Second Item", text: "Some value 2..." },
{ value: "c", title: "Third Item", text: "Some value 3..." },
]
Components
先ほどの章でも少し取り上げましたが、コンポーネントに関してはArk UIを基に作成したためガラリと変わっています。
基本的にはArk UIのリファレンスを参考にしつつ実装するのが良いと思います。
また、コンポーネントを使用する際は以下のCLIコマンドでスニペットを追加してあげる必要があります。
npx @chakra-ui/cli snippet add
V3ではPagination
などの新しいコンポーネントが追加された反面、シンプルになった影響で細かい調整などがしにくくなっています。
例えば、V3ではHooks
が一部を除き無くなっています。(useBreakpointValue
等は現在も使用可能)
そのため、Radio
などで今まで使っていたuseRadio
やuseRadioGroup
を使用されている場合は代替手段としてreact-use
やusehooks-ts
を使用する必要があります。
おわりに
ここまでご覧いただきありがとうございます🙇
見た感じ、Panda CSSとArk UIに触れたことがある方にとってはより親しみやすくなったんじゃないでしょうか。
Chakra UIの今回のメジャーアップデートはかなり破壊的変更が満載ですので、プロダクトに規模によってかなり慎重に検討する必要があるかと思います。
今回は特に変わったところをご紹介したので、他にも気になることがあれば教えていただければと思います🫡