Communitygithub.com

Chakra UI 迁移:v2 → v3

将 Chakra UI 项目从 v2 迁移到 v3,涵盖包更改、codemod、Provider 设置、颜色模式、属性重命名、复合组件、主题化、配方和 Next.js 更新。

Chakra UI 迁移:v2 → v3 是什么?

该技能提供从 Chakra UI v2 到 v3 的全面迁移指南,适用于使用 Chakra UI 的 React 项目(特别是 Next.js)。它详细说明了迁移步骤,包括检查当前项目状态、更新依赖(移除 @chakra-ui/icons 等包并安装 @chakra-ui/react)、运行官方 codemod 自动处理组件重命名和属性更新、以及手动调整 Provider、颜色模式、主题配置(使用 createSystem 替代 extendTheme)和复合组件(如 Modal → Dialog.Root)的模式。该技能还涵盖了属性重命名(如 isDisabled → disabled)、使用 asChild 模式替换 @chakra-ui/next-js、以及使用新的 recipe 和 slot recipe API 进行主题化。最后,它提供了验证清单和澄清问题的指导,以确保迁移的完整性和准确性。

兼容平台~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 可处理大部分机械性更改:组件重命名、属性更新、导入重写以及复合组件重构。但它不能替代人工审查——请计划审核输出。

先进行试运行(不更改文件):

npx @chakra-ui/codemod upgrade --dry

检查它提议的更改。满意后:

npx @chakra-ui/codemod upgrade

运行 codemod 后,先提交更改再手动编辑,这样您就可以有一个清晰的 diff 来作为工作基础。


步骤 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 中的自定义主题

用 createSystem 替换 extendTheme:

// 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 — 属性重命名

这些布尔属性和样式属性在 v3 中被重命名,以与 HTML 和现代 React 约定保持一致。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>标题</ModalHeader>
    <ModalBody>正文</ModalBody>
    <ModalFooter><Button onClick={onClose}>关闭</Button></ModalFooter>
  </ModalContent>
</Modal>

// v3
<Dialog.Root open={open} onOpenChange={({ open }) => setOpen(open)}>
  <Dialog.Backdrop />
  <Dialog.Positioner>
    <Dialog.Content>
      <Dialog.Header><Dialog.Title>标题</Dialog.Title></Dialog.Header>
      <Dialog.Body>正文</Dialog.Body>
      <Dialog.Footer><Button onClick={() => setOpen(false)}>关闭</Button></Dialog.Footer>
      <Dialog.CloseTrigger />
    </Dialog.Content>
  </Dialog.Positioner>
</Dialog.Root>

复合组件重写

v3 采用一致的复合组件 API。codemod 可处理其中许多更改,但复杂的自定义用法需要手动审查。

Checkbox

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

// v3
<Checkbox.Root checked={val} onCheckedChange={fn}>
  <Checkbox.Control><Checkbox.Indicator /></Checkbox.Control>
  <Checkbox.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>邮箱</FormLabel>
  <Input type="email" />
  <FormErrorMessage>{error}</FormErrorMessage>
  <FormHelperText>我们绝不会分享您的邮箱。</FormHelperText>
</FormControl>

// v3
<Field.Root invalid={!!error} required>
  <Field.Label>邮箱</Field.Label>
  <Input type="email" />
  <Field.ErrorText>{error}</Field.ErrorText>
  <Field.HelpText>我们绝不会分享您的邮箱。</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">关于</NextLink></ChakraLink>

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

步骤 8 — 主题化迁移

styleConfig 和 multiStyleConfig → 配方

// v3 — 单一组件(配方)
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 — 插槽配方
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" } },
})

自定义令牌的类型生成

添加自定义令牌、语义令牌、配方或插槽配方后,运行 typegen 以保持 TypeScript 类型同步:

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

复杂的主题迁移——如果您正在迁移包含大量自定义令牌、语义令牌或多部分组件样式的庞大 v2 主题,请使用 chakra-ui-theming 技能。它深入涵盖了完整的令牌/配方/插槽配方 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 — 解决所有类型错误
  • Lint: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.

相关技能