Communitygithub.com

0xAlchemist-cs/personal-ui-system

將 Chakra UI 專案從 v2 遷移至 v3,涵蓋套件變更、codemod、Provider 設定、色彩模式、屬性重新命名、複合元件、主題設定、recipes 及 Next.js 更新。

personal-ui-system 是什麼?

這個技能專為協助開發者將 Chakra UI 專案從 v2 遷移至 v3 而設計,涵蓋完整的遷移流程。它會引導使用者逐步完成專案檢查、套件更新(包括移除像 `@chakra-ui/icons` 和 `framer-motion` 這類僅支援 v2 的相依套件)、執行官方 codemod 進行機械性更改,以及手動調整主題設定。此技能明確支援 Next.js(App Router 與 Pages Router)、Vite 及純 React 環境。它在處理色彩模式遷移(透過 `next-themes`)以及將舊的 `extendTheme`、`styleConfig` 和 `multiStyleConfig` 語法轉換為新的 `createSystem`、`defineRecipe` 與 `defineSlotRecipe` API 時表現出色。其中一個主要亮點是複合元件(如 `Modal` → `Dialog.Root`)的重構指南,並對所有屬性重新命名(如 `isDisabled` → `disabled`、`colorScheme` → `colorPalette`)提供了詳細對照表。此技能也包含了完整的驗證檢查清單,涵蓋 TypeScript、lint、建置、色彩模式切換及互動元件測試,以確保遷移完成後一切正常運作。

相容平台~Claude Code~Codex CLI~Cursor
npx skills add https://github.com/0xAlchemist-cs/personal-ui-system/tree/HEAD/.agents/skills/chakra-ui-migrate

在你喜歡的 AI 中提問

開啟一個已預先載入此 Agent Skill 的新對話。

說明文件

Chakra UI 遷移:v2 → v3

您正在引導開發人員將其專案從 Chakra UI v2 遷移至 v3。請依序完成以下步驟。請先檢查專案——切勿猜測套件版本或使用的框架。

Node 版本需求: Chakra UI v3 需要 Node >= 20.x。若環境不確定,請先確認後再繼續。


步驟 1 — 檢查專案

閱讀以下檔案以了解當前狀態:

package.json

檢查項目:

  • 目前的 @chakra-ui/react 版本(v2.x 還是 v3.x)
  • 相關套件:@chakra-ui/icons、@chakra-ui/hooks、@chakra-ui/next-js、@emotion/styled、framer-motion
  • 框架:Next.js(App Router 或 Pages Router)、Vite、純 React
  • 套件管理工具(根據鎖定檔案:pnpm-lock.yaml、yarn.lock、bun.lock、package-lock.json)

必要時也抽查關鍵檔案:

  • Provider / 主題設定(_app.tsx、layout.tsx、theme.ts)
  • 色彩模式使用方式(ColorModeScript、useColorMode、useColorModeValue)
  • 任何顯示大量 v2 模式且已過時的元件檔案

步驟 2 — 更新套件

移除僅限 v2 的相依套件

# npm
npm uninstall @chakra-ui/icons @chakra-ui/hooks @chakra-ui/next-js @emotion/styled framer-motion

# pnpm
pnpm remove @chakra-ui/icons @chakra-ui/hooks @chakra-ui/next-js @emotion/styled framer-motion

# yarn
yarn remove @chakra-ui/icons @chakra-ui/hooks @chakra-ui/next-js @emotion/styled framer-motion

@emotion/styled 和 framer-motion 在 v3 中已不再需要。

安裝 v3 核心套件

# npm
npm install @chakra-ui/react @emotion/react

# pnpm
pnpm add @chakra-ui/react @emotion/react

# yarn
yarn add @chakra-ui/react @emotion/react

已移除套件的替代方案

已移除替代方案
@chakra-ui/iconslucide-react 或 react-icons
@chakra-ui/hooksreact-use 或 usehooks-ts
@chakra-ui/next-jsasChild 屬性模式(請參閱 Next.js 章節)

步驟 3 — 執行 codemod

官方 codemod 能處理大多數機械性變更:元件重新命名、屬性更新、import 重寫以及複合元件重構。但它不能取代手動審查——請務必檢查其輸出。

先進行試執行(不變更檔案):

npx @chakra-ui/codemod upgrade --dry

審查它提出的變更。確認無誤後:

npx @chakra-ui/codemod upgrade

執行 codemod 後,先提交變更再做手動編輯,這樣您就能以乾淨的差異記錄作為工作基礎。


步驟 4 — 更新 Provider

舊版 v2 模式

// v2
import { ChakraProvider } from "@chakra-ui/react"
import theme from "./theme"

;<ChakraProvider theme={theme}>{children}</ChakraProvider>

新版 v3 模式(使用 Chakra CLI 片段)

產生 Provider 和元件片段:

npx @chakra-ui/cli snippet add

這會建立 components/ui/provider.tsx(以及 toaster 和 tooltip 片段),並自動安裝所需的 npm 相依套件——包括 next-themes。匯入並使用它:

// v3 — app/layout.tsx(Next.js App Router)
import { Provider } from "@/components/ui/provider"

;<html lang="en" suppressHydrationWarning>
  <body>
    <Provider>{children}</Provider>
  </body>
</html>

Provider 檔案已包含 "use client"——請勿在 layout.tsx 中再次添加。關於 Pages Router 的放置方式,請參閱 Next.js 章節。

v3 中的自訂主題

將 extendTheme 替換為 createSystem:

// v2
import { extendTheme } from "@chakra-ui/react"
// v3
import { createSystem, defaultConfig, defineConfig } from "@chakra-ui/react"

export const theme = extendTheme({ colors: { brand: { 500: "#2196f3" } } })

const config = defineConfig({
  theme: { tokens: { colors: { brand: { 500: { value: "#2196f3" } } } } },
})
export const system = createSystem(defaultConfig, config)

透過 value={system} 將 system 傳遞給 ChakraProvider。


步驟 5 — 色彩模式遷移

移除所有 v2 色彩模式模式

// 移除這些 v2 的匯入和使用:
import { ColorModeScript } from "@chakra-ui/react"
// ❌
import { useColorMode } from "@chakra-ui/react"
// ❌(改用 next-themes)
import { useColorModeValue } from "@chakra-ui/react"
// ❌(改用 CSS tokens)
import { DarkMode, LightMode } from "@chakra-ui/react"
// ❌

// 也從 _document.tsx 中移除:
;<ColorModeScript initialColorMode={theme.config.initialColorMode} /> // ❌

v3 色彩模式方法

色彩模式由 next-themes 透過產生的 Provider 來處理。使用能自動回應當前色彩模式的語意化 tokens:

// 使用 Chakra 語意化 tokens——它們在暗色模式下會自動切換
<Box color="fg.default" bg="bg.subtle">
  ...
</Box>

若要製作色彩模式切換開關,請使用產生的 components/ui/color-mode.tsx 片段或直接使用 next-themes 提供的 useColorMode。


步驟 6 — 屬性重新命名

為了與 HTML 及現代 React 慣例保持一致,這些布林值和樣式屬性在 v3 中已被重新命名。codemod 會捕捉到其中大部分,但請在之後手動驗證。

布林值屬性

v2v3
isOpenopen
defaultIsOpendefaultOpen
isDisableddisabled
isInvalidinvalid
isRequiredrequired
isReadOnlyreadOnly
isCheckedchecked
isLoadedloaded
isIndeterminateindeterminate

樣式與佈局屬性

v2v3
colorSchemecolorPalette
noOfLineslineClamp
truncatedtruncate
spacing(Stack)gap
applytextStyle 或 layerStyle

巢狀樣式屬性

// v2 — 使用巢狀偽選擇器的 sx
<Box sx={{ "&:hover": { color: "blue.500" } }} />

// v3 — 搭配 "&" 選擇器的 css 屬性
<Box css={{ "&:hover": { color: "blue.500" } }} />

步驟 7 — 元件遷移

已重新命名的元件

v2v3
ModalDialog
FormControlField
SelectNativeSelect
AlertDialogAlertDialog(複合元件,請見下方)

Modal 是最常見的重新命名——每個 <Modal>、<ModalOverlay>、<ModalContent>、<ModalHeader>、<ModalBody>、<ModalFooter> 和 <ModalCloseButton> 都會變成 Dialog.* 複合元件的一部分:

// v2
<Modal isOpen={open} onClose={onClose}>
  <ModalOverlay />
  <ModalContent>
    <ModalHeader>Title</ModalHeader>
    <ModalBody>Body</ModalBody>
    <ModalFooter><Button onClick={onClose}>Close</Button></ModalFooter>
  </ModalContent>
</Modal>

// v3
<Dialog.Root open={open} onOpenChange={({ open }) => setOpen(open)}>
  <Dialog.Backdrop />
  <Dialog.Positioner>
    <Dialog.Content>
      <Dialog.Header><Dialog.Title>Title</Dialog.Title></Dialog.Header>
      <Dialog.Body>Body</Dialog.Body>
      <Dialog.Footer><Button onClick={() => setOpen(false)}>Close</Button></Dialog.Footer>
      <Dialog.CloseTrigger />
    </Dialog.Content>
  </Dialog.Positioner>
</Dialog.Root>

複合元件重寫

v3 採用一致的複合元件 API。codemod 會處理其中多數情況,但複雜的自訂用法需要手動審查。

Checkbox

// v2
<Checkbox isChecked={val} onChange={fn}>Label</Checkbox>

// v3
<Checkbox.Root checked={val} onCheckedChange={fn}>
  <Checkbox.Control><Checkbox.Indicator /></Checkbox.Control>
  <Checkbox.Label>Label</Checkbox.Label>
</Checkbox.Root>

Progress

// v2
<Progress value={60} colorScheme="blue" />

// v3
<Progress.Root value={60} colorPalette="blue">
  <Progress.Track><Progress.Range /></Progress.Track>
</Progress.Root>

Accordion

// v2
<Accordion><AccordionItem><AccordionButton /><AccordionPanel /></AccordionItem></Accordion>

// v3
<Accordion.Root>
  <Accordion.Item value="item-1">
    <Accordion.ItemTrigger />
    <Accordion.ItemContent />
  </Accordion.Item>
</Accordion.Root>

FormControl → Field

// v2
<FormControl isInvalid={!!error} isRequired>
  <FormLabel>Email</FormLabel>
  <Input type="email" />
  <FormErrorMessage>{error}</FormErrorMessage>
  <FormHelperText>We'll never share your email.</FormHelperText>
</FormControl>

// v3
<Field.Root invalid={!!error} required>
  <Field.Label>Email</Field.Label>
  <Input type="email" />
  <Field.ErrorText>{error}</Field.ErrorText>
  <Field.HelpText>We'll never share your email.</Field.HelpText>
</Field.Root>

所有 FormControl 的子部分都對應到 Field.*:

  • FormLabel → Field.Label
  • FormErrorMessage → Field.ErrorText
  • FormHelperText → Field.HelpText
  • FormControl 的屬性 isInvalid、isRequired、isDisabled → invalid、required、disabled

Dialog / Drawer / Menu / Tabs 遵循相同的複合模式:使用 ComponentName.Root、.Trigger、.Content、.Item 等。請查閱 Chakra UI v3 文件,了解每個元件的具體複合 API。

Next.js Image 和 Link(取代 @chakra-ui/next-js)

// v2 — @chakra-ui/next-js
import { LinkOverlay } from "@chakra-ui/next-js"

// v3 — asChild 模式
import NextLink from "next/link"
<ChakraLink asChild><NextLink href="/about">About</NextLink></ChakraLink>

import NextImage from "next/image"
<ChakraImage asChild><NextImage src="..." alt="..." /></ChakraImage>

步驟 8 — 主題設定遷移

styleConfig 和 multiStyleConfig → recipes

// v3 — 單一元件(recipe)
import { defineRecipe } from "@chakra-ui/react"

// v2
const buttonStyle = {
  baseStyle: { fontWeight: "bold" },
  variants: { solid: { bg: "blue.500" } },
  defaultProps: { variant: "solid" },
}

const buttonRecipe = defineRecipe({
  base: { fontWeight: "bold" },
  variants: { variant: { solid: { bg: "blue.500" } } },
  defaultVariants: { variant: "solid" },
})
// v3 — slot recipe
import { defineSlotRecipe } from "@chakra-ui/react"

// v2 — multiStyleConfig(多部分元件)
const cardStyle = multiStyleConfig({
  parts: ["root", "header"],
  baseStyle: { root: { bg: "white" }, header: { fontWeight: "bold" } },
})

const cardSlotRecipe = defineSlotRecipe({
  slots: ["root", "header"],
  base: { root: { bg: "white" }, header: { fontWeight: "bold" } },
})

自訂 tokens 的 Typegen

在新增自訂 tokens、語意化 tokens、recipes 或 slot recipes 之後,執行 typegen 以保持 TypeScript 型別同步:

npx @chakra-ui/cli typegen ./theme.ts

複雜的主題設定遷移——如果您正在遷移一個包含許多自訂 tokens、語意化 tokens 或多部分元件樣式的大型 v2 主題,請使用 chakra-ui-theming 技能。它會深入介紹完整的 token/recipe/slot-recipe API,是比本節更好的指南。


步驟 9 — Next.js 特定事項

App Router

  • 將 <Provider> 放在 app/layout.tsx 中(伺服器元件——不使用 "use client")
  • 產生的 components/ui/provider.tsx 已經有 "use client"
  • 在 <html> 上添加 suppressHydrationWarning 以防止色彩模式閃爍
  • 不要將整個應用程式或佈局包裹在 "use client" 中

Pages Router

// pages/_app.js
import { Provider } from "@/components/ui/provider"

export default function App({ Component, pageProps }) {
  return (
    <Provider>
      <Component {...pageProps} />
    </Provider>
  )
}

從 pages/_document.tsx 中移除所有 ColorModeScript——v3 中不再使用。


步驟 10 — 驗證檢查清單

完成遷移後,請逐一核對以下項目:

  • 重新安裝相依套件:npm install / pnpm install
  • TypeScript:npx tsc --noEmit——解決所有型別錯誤
  • 程式碼檢查:npm run lint
  • 建置:npm run build
  • 視覺上確認色彩模式切換(亮色 ↔ 暗色)
  • 測試互動元件:Dialog、Drawer、Menu、Tabs、Accordion
  • 測試表單元件:Checkbox、Select/NativeSelect、Input、Radio
  • 檢查關鍵頁面的視覺回歸
  • 搜尋程式碼庫中殘留的 v2 匯入:
    grep -r "ColorModeScript\|useColorModeValue\|extendTheme\|styleConfig\|@chakra-ui/icons\|@chakra-ui/next-js" src/
    

釐清問題(當上下文不明確時)

如果使用者的版本、框架或範圍不明確,請詢問:

  1. 「您目前的 @chakra-ui/react 是哪個版本?」
  2. 「您使用的是 Next.js App Router、Pages Router、Vite 還是純 React?」
  3. 「您是要遷移整個程式碼庫,還是只遷移特定元件?」

如果您在沒有詢問的情況下繼續進行,請明確說明您的假設。

Individual skills in this repo

This repo contains 2 individual skills — each has its own dedicated page.

相關技能