Skip to Content
文档

迁移到 v3

如何从 Chakra UI v2.x 迁移到 v3.x

warning

我们建议使用 LLMs.txt 文件,以便大型语言模型能够访问 Chakra UI v3 文档。

¥We recommend using the LLMs.txt files to make the Chakra UI v3 documentation available to large language models.

步骤

¥Steps

所需的最低 Node 版本为 Node.20.x

1

更新软件包

¥Update Packages

删除未使用的包:@emotion/styledframer-motion。Chakra UI 中不再需要这些包。

¥Remove the unused packages: @emotion/styled and framer-motion. These packages are no longer required in Chakra UI.

npm uninstall @emotion/styled framer-motion

安装以下软件包的更新版本:@chakra-ui/react@emotion/react

¥Install updated versions of the packages: @chakra-ui/react and @emotion/react.

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

接下来,使用 CLI 代码片段安装组件代码片段。代码片段提供 Chakra 组件的预构建组合,以节省你的时间并让你掌控一切。

¥Next, install component snippets using the CLI snippets. Snippets provide pre-built compositions of Chakra components to save you time and put you in charge.

npx @chakra-ui/cli snippet add
2

重构自定义主题

¥Refactor Custom Theme

将你的自定义主题移至专用的 theme.jstheme.ts 文件。使用 createSystemdefaultConfig 配置你的主题。

¥Move your custom theme to a dedicated theme.js or theme.ts file. Use createSystem and defaultConfig to configure your theme.

修改前

¥Before

import { extendTheme } from "@chakra-ui/react"

export const theme = extendTheme({
  fonts: {
    heading: `'Figtree', sans-serif`,
    body: `'Figtree', sans-serif`,
  },
})

修改后

¥After

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` },
      },
    },
  },
})

所有 token 值都需要封装在一个带有 value 键的对象中。了解更多关于 token 此处 的信息。

3

更新 Chakra 提供程序

¥Update ChakraProvider

将 ChakraProvider 的导入从 @chakra-ui/react 更新为代码片段中的导入。接下来,将 theme 属性重命名为 value,以匹配新的基于系统的主题方法。

¥Update the ChakraProvider import from @chakra-ui/react to the one from the snippets. Next, rename the theme prop to value to match the new system-based theming approach.

修改前

¥Before

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

export const App = ({ Component }) => (
  <ChakraProvider theme={theme}>
    <Component />
  </ChakraProvider>
)

修改后

¥After

import { Provider } from "@/components/ui/provider"
import { defaultSystem } from "@chakra-ui/react"

export const App = ({ Component }) => (
  <Provider>
    <Component />
  </Provider>
)
import { ColorModeProvider } from "@/components/ui/color-mode"
import { ChakraProvider, defaultSystem } from "@chakra-ui/react"

export function Provider(props) {
  return (
    <ChakraProvider value={defaultSystem}>
      <ColorModeProvider {...props} />
    </ChakraProvider>
  )
}

如果你有自定义主题,请将 defaultSystem 替换为自定义 system

Provider 组件由 Chakra 中的 ChakraProvidernext-themes 中的 ThemeProvider 组成。

¥The Provider component compose the ChakraProvider from Chakra and ThemeProvider from next-themes

改进

¥Improvements

  • 性能:4x 改进了协调性能,1.6x 改进了重新渲染性能

  • 命名空间导入:使用点符号导入组件,使导入更简洁

  import { Accordion } from "@chakra-ui/react"

  const Demo = () => {
    return (
      <Accordion.Root>
        <Accordion.Item>
          <Accordion.ItemTrigger />
          <Accordion.ItemContent />
        </Accordion.Item>
      </Accordion.Root>
    )
  }
  • TypeScript:改进了样式属性和令牌的 IntelliSense 和类型推断。

  • 多态性:放宽了 as 属性的类型限制,转而使用 asChild 属性。此模式的灵感来自 Radix Primitives 和 Ark UI。

移除的功能

¥Removed Features

颜色模式

¥Color Mode

  • ColorModeProvideruseColorMode 已被移除,取而代之的是 next-themes

  • LightModeDarkModeColorModeScript 组件已被移除。现在你必须使用 className="light"className="dark" 来强制主题。

  • useColorModeValue 已从 next-themes 中移除,取而代之的是 useTheme

note

我们通过 CLI 提供颜色模式的代码片段,以帮助你使用 next-themes 快速设置颜色模式。

¥We provide snippets for color mode via the CLI to help you set up color mode quickly using next-themes

钩子

¥Hooks

我们删除了 hooks 包,转而使用专用的、健壮的库,例如 react-useusehooks-ts

¥We removed the hooks package in favor of using dedicated, robust libraries like react-use and usehooks-ts

我们现在仅提供 useBreakpointValueuseCallbackRefuseDisclosureuseControllableStateuseMediaQuery 钩子函数。

¥The only hooks we ship now are useBreakpointValue, useCallbackRef, useDisclosure, useControllableState and useMediaQuery.

样式配置

¥Style Config

我们删除了 styleConfigmultiStyleConfig 概念,转而使用配方和插槽配方。此模式的灵感来自 Panda CSS。

¥We removed the styleConfig and multiStyleConfig concept in favor of recipes and slot recipes. This pattern was inspired by Panda CSS.

Next.js 包

¥Next.js package

我们已移除 @chakra-ui/next-js 包,转而使用 asChild 属性,以提高灵活性。

¥We've removed the @chakra-ui/next-js package in favor of using the asChild prop for better flexibility.

要设置 Next.js 图片组件的样式,请在 Box 组件上使用 asChild 属性。

¥To style the Next.js image component, use the asChild prop on the Box component.

<Box asChild>
  <NextImage />
</Box>

要设置 Next.js 链接组件的样式,请在 Link 组件上使用 asChild 属性。

¥To style the Next.js link component, use the asChild prop on the Link component

<Link isExternal asChild>
  <NextLink />
</Link>

主题工具

¥Theme Tools

我们已移除此包,转而使用 CSS 颜色混合。

¥We've removed this package in favor using CSS color mix.

修改前

¥Before

我们使用 JS 解析颜色,然后应用透明度。

¥We used JS to resolve the colors and then apply the transparency

defineStyle({
  bg: transparentize("blue.200", 0.16)(theme),
  // -> rgba(0, 0, 255, 0.16)
})

修改后

¥After

我们现在使用 CSS color-mix

¥We now use CSS color-mix

defineStyle({
  bg: "blue.200/16",
  // -> color-mix(in srgb, var(--chakra-colors-200), transparent 16%)
})

forwardRef

由于 as 属性的简化,我们不再提供自定义 forwardRef。建议直接使用 React 中的 forwardRef

¥Due to the simplification of the as prop, we no longer provide a custom forwardRef. Prefer to use forwardRef from React directly.

修改前:

¥Before:

import { Button as ChakraButton, forwardRef } from "@chakra-ui/react"

const Button = forwardRef<ButtonProps, "button">(function Button(props, ref) {
  return <ChakraButton ref={ref} {...props} />
})

修改后:

¥After:

import { Button as ChakraButton } from "@chakra-ui/react"
import { forwardRef } from "react"

const Button = forwardRef<HTMLButtonElement, ButtonProps>(
  function Button(props, ref) {
    return <ChakraButton ref={ref} {...props} />
  },
)

图标

¥Icons

已删除 @chakra-ui/icons 包。建议改用 lucide-reactreact-icons

¥Removed @chakra-ui/icons package. Prefer to use lucide-react or react-icons instead.

Storybook 插件

¥Storybook Addon

我们已移除 Storybook 插件,转而使用 @storybook/addon-themeswithThemeByClassName 助手。

¥We're removed the storybook addon in favor of using @storybook/addon-themes and withThemeByClassName helper.

import { ChakraProvider, defaultSystem } from "@chakra-ui/react"
import { withThemeByClassName } from "@storybook/addon-themes"
import type { Preview, ReactRenderer } from "@storybook/react"

const preview: Preview = {
  decorators: [
    withThemeByClassName<ReactRenderer>({
      defaultTheme: "light",
      themes: {
        light: "",
        dark: "dark",
      },
    }),
    (Story) => (
      <ChakraProvider value={defaultSystem}>
        <Story />
      </ChakraProvider>
    ),
  ],
}

export default preview

移除的组件

¥Removed Components

  • 堆栈项:你不再需要这样做。请改用 Box

  • FocusLock:我们不再提供焦点锁定组件。直接安装并使用 react-focus-lock

  • AlertDialog

    • Dialog 组件替换并设置 role=alertdialog

    • leastDestructiveRef 属性设置为 initialFocusElDialog.Root 组件

CircularProgress

  • 重命名为 ProgressCircle,现在使用复合组件。

  • isIndeterminate 变为 value={null}

  • thickness 属性变为 --thickness CSS 变量

  • color 属性在 ProgressCircle.Range 上变为 stroke 属性

修改前:

¥Before:

<CircularProgress
  value={75}
  thickness="4px"
  color="blue.500"
  isIndeterminate={false}
/>

修改后:

¥After:

<ProgressCircle.Root value={75}>
  <ProgressCircle.Circle css={{ "--thickness": "4px" }}>
    <ProgressCircle.Track />
    <ProgressCircle.Range stroke="blue.500" />
  </ProgressCircle.Circle>
</ProgressCircle.Root>

不确定进度:

¥For indeterminate progress:

<ProgressCircle.Root value={null}>
  <ProgressCircle.Circle>
    <ProgressCircle.Track />
    <ProgressCircle.Range />
  </ProgressCircle.Circle>
</ProgressCircle.Root>

StackDivider

  • 不再作为单独的组件提供

  • 在堆叠项目之间使用显式 Stack.Separator 组件

修改前:

¥Before:

<VStack divider={<StackDivider borderColor="gray.200" />} spacing={4}>
  <Box>Item 1</Box>
  <Box>Item 2</Box>
  <Box>Item 3</Box>
</VStack>

修改后:

¥After:

<VStack gap={4}>
  <Box>Item 1</Box>
  <Stack.Separator borderColor="gray.200" />
  <Box>Item 2</Box>
  <Stack.Separator borderColor="gray.200" />
  <Box>Item 3</Box>
</VStack>

属性变化

¥Prop Changes

布尔属性

¥Boolean Props

将布尔属性的命名约定从 is<X> 更改为 <x>

¥Changed naming convention for boolean properties from is<X> to <x>

  • isOpen -> open

  • defaultIsOpen -> defaultOpen

  • isDisabled -> disabled

  • isInvalid -> invalid

  • isRequired -> required

配色方案属性

¥ColorScheme Prop

colorScheme 属性已更改为 colorPalette

¥The colorScheme prop has been changed to colorPalette

修改前

¥Before

  • 你只能在组件的主题中使用 colorScheme

  • colorScheme 与 HTML 元素中的原生 colorScheme 属性冲突

<Button colorScheme="blue">Click me</Button>

修改后

¥After

  • 你现在可以在任何地方使用 colorPalette
<Button colorPalette="blue">Click me</Button>

在任何组件中的用法,你可以执行以下操作:

¥Usage in any component, you can do something like:

<Box colorPalette="red">
  <Box bg="colorPalette.400">Some box</Box>
  <Text color="colorPalette.600">Some text</Text>
</Box>

如果你使用自定义颜色,则必须定义两件事才能使 colorPalette 正常工作:

¥If you are using custom colors, you must define two things to make colorPalette work:

  • tokens

    50-950 调色板

  • semanticTokens

    solidcontrastfgmutedsubtleemphasizedfocusRing 颜色键

theme.ts

import { createSystem, defaultConfig } from "@chakra-ui/react"

export const system = createSystem(defaultConfig, {
  theme: {
    tokens: {
      colors: {
        brand: {
          50: { value: "#e6f2ff" },
          100: { value: "#e6f2ff" },
          200: { value: "#bfdeff" },
          300: { value: "#99caff" },
          // ...
          950: { value: "#001a33" },
        },
      },
    },
    semanticTokens: {
      colors: {
        brand: {
          solid: { value: "{colors.brand.500}" },
          contrast: { value: "{colors.brand.100}" },
          fg: { value: "{colors.brand.700}" },
          muted: { value: "{colors.brand.100}" },
          subtle: { value: "{colors.brand.200}" },
          emphasized: { value: "{colors.brand.300}" },
          focusRing: { value: "{colors.brand.500}" },
        },
      },
    },
  },
})

了解更多关于 此处 的信息。

渐变属性

¥Gradient Props

渐变样式属性简化为 gradientgradientFromgradientTo 属性。这降低了解析渐变字符串的运行时性能成本,并允许更好的类型推断。

¥Gradient style prop simplified to gradient and gradientFrom and gradientTo props. This reduces the runtime performance cost of parsing the gradient string, and allows for better type inference.

修改前

¥Before

<Box bgGradient="linear(to-r, red.200, pink.500)" />

修改后

¥After

<Box bgGradient="to-r" gradientFrom="red.200" gradientTo="pink.500" />

调色板

¥Color Palette

  • 现在所有组件的默认调色板均为 gray,但你可以在主题中配置。

  • 默认主题调色板大小已增加到 11 种色调,以允许更多颜色变化。

    修改前

  const colors = {
    // ...
    gray: {
      50: "#F7FAFC",
      100: "#EDF2F7",
      200: "#E2E8F0",
      300: "#CBD5E0",
      400: "#A0AEC0",
      500: "#718096",
      600: "#4A5568",
      700: "#2D3748",
      800: "#1A202C",
      900: "#171923",
    },
  }

修改后

¥After

  const colors = {
    // ...
    gray: {
      50: { value: "#fafafa" },
      100: { value: "#f4f4f5" },
      200: { value: "#e4e4e7" },
      300: { value: "#d4d4d8" },
      400: { value: "#a1a1aa" },
      500: { value: "#71717a" },
      600: { value: "#52525b" },
      700: { value: "#3f3f46" },
      800: { value: "#27272a" },
      900: { value: "#18181b" },
      950: { value: "#09090b" },
    },
  }

样式属性

¥Style Props

更改了部分样式属性的命名约定

¥Changed the naming convention for some style props

  • noOfLines -> lineClamp

  • truncated -> truncate

  • _activeLink -> _currentPage

  • _activeStep -> _currentStep

  • _mediaDark -> _osDark

  • _mediaLight -> _osLight

示例:

¥Examples:

// Before
<Text noOfLines={2}>
  Long text that will be clamped to 2 lines
</Text>

<Text truncated>
  This text will be truncated with ellipsis
</Text>

// After
<Text lineClamp={2}>
  Long text that will be clamped to 2 lines
</Text>

<Text truncate>
  This text will be truncated with ellipsis
</Text>

我们删除了 apply 属性,转而使用 textStylelayerStyles

¥We removed the apply prop in favor of textStyle or layerStyles

嵌套样式

¥Nested Styles

我们改变了在 Chakra UI 组件中编写嵌套样式的方式。

¥We have changed the way you write nested styles in Chakra UI components.

修改前

¥Before

使用 sx__css 属性编写嵌套样式,有时嵌套样式无法自动补齐。

¥Write nested styles using the sx or __css prop, and you sometimes don't get auto-completion for nested styles.

<Box
  sx={{
    svg: { color: "red.500" },
  }}
/>

修改后

¥After

使用 css 属性编写嵌套样式。所有嵌套选择器都需要使用 & 符号 & 前缀。

¥Write nested styles using the css prop. All nested selectors require the use of the ampersand & prefix

<Box
  css={{
    "& svg": { color: "red.500" },
  }}
/>

这样做有两个原因:

¥This was done for two reasons:

  • 更快的样式处理:之前我们必须检查样式键是样式属性还是选择器,这总体来说开销很大。

  • 更好的输入:这更容易键入嵌套的样式属性,使其具有强类型

组件更改

¥Component Changes

ChakraProvider

  • 移除 theme 属性,改为传递 system 属性。导入 defaultSystem 模块而不是 theme

  • 移除 resetCss 属性,改为将 preflight: false 属性传递给 createSystem 函数。

修改前

¥Before

<ChakraProvider resetCss={false}>
  <Component />
</ChakraProvider>

修改后

¥After

const system = createSystem(defaultConfig, { preflight: false })

<Provider value={system}>
  <Component />
</Provider>
  • 移除了对配置提示框选项的支持。请将其传递给 components/ui/toaster.tsx 文件中的 createToaster 函数。

模态窗口

¥Modal

  • 已重命名为 Dialog

  • 移除 isCentered 属性,以便使用 placement=center 属性。

  • 移除 isOpenonClose 属性,改为使用 openonOpenChange 属性。

头像

¥Avatar

  • 移除 max 属性,以便用户空间控制。

  • 删除多余的标签部分

  • 将图片相关属性移至 Avatar.Image 组件

  • 将后备图标移至 Avatar.Fallback 组件

  • name 属性移至 Avatar.Fallback 组件

门户

¥Portal

  • 移除 appendToParentPortal 属性,以便使用 containerRef 属性。

  • 删除 PortalManager 组件

进度

¥Progress

  • 现在可以使用带有 Progress.RootProgress.TrackProgress.Range 的复合组件

  • hasStripe 属性重命名为 striped

  • isAnimated 属性重命名为 animated

  • colorScheme 属性重命名为 colorPalette

修改前:

¥Before:

<Progress hasStripe isAnimated value={75} colorScheme="blue" />

修改后:

¥After:

<Progress.Root striped animated value={75} colorPalette="blue">
  <Progress.Track>
    <Progress.Range />
  </Progress.Track>
</Progress.Root>

堆叠

¥Stack

  • spacing 更改为 gap

  • 移除 StackItem 属性,改为直接使用 Box 组件。

选择

¥Select

现在称为 NativeSelect,并公开所有部分。

¥Now called NativeSelect and exposes all parts now.

修改前:

¥Before:

<Select placeholder="Select option">
  <option value="option1">Option 1</option>
  <option value="option2">Option 2</option>
  <option value="option3">Option 3</option>
</Select>

修改后:

¥After:

<NativeSelect.Root size="sm" width="240px">
  <NativeSelect.Field placeholder="Select option">
    <option value="option1">Option 1</option>
    <option value="option2">Option 2</option>
    <option value="option3">Option 3</option>
  </NativeSelect.Field>
  <NativeSelect.Indicator />
</NativeSelect.Root>

更改图标

¥Changing the icon

修改前:

¥Before:

<Select icon={<MdArrowDropDown />} placeholder="Woohoo! A new icon" />

修改后:

¥After:

<NativeSelect.Indicator>
  <MdArrowDropDown />
</NativeSelect.Indicator>

收起

¥Collapse

  • Collapse 重命名为 Collapsible 命名空间

  • in 重命名为 open

  • animateOpacity 已被移除,请使用关键帧动画 expand-heightcollapse-height 代替

修改前

¥Before

<Collapse in={isOpen} animateOpacity>
  Some content
</Collapse>

修改后

¥After

<Collapsible.Root open={isOpen}>
  <Collapsible.Content>Some content</Collapsible.Content>
</Collapsible.Root>

图片

¥Image

  • 现在渲染原生 img,没有任何回退。

  • 移除 fallbackSrc,因为它会导致服务器端渲染 (SSR) 问题。

  • 删除 useImage 钩子

  • 移除 Img,以便直接使用 Image 组件。

PinInput

  • valuedefaultValue 更改为使用 string[] 而不是 string

  • onChange 属性现为 onValueChange

  • 添加新的 PinInput.ControlPinInput.Label 组件

  • PinInput.Root 现在默认渲染 div 元素。考虑与 StackGroup 结合使用以获得更好的布局控制。

  • onComplete 属性现为 onValueComplete

NumberInput

  • NumberInputStepper 重命名为 NumberInput.Control

  • NumberInputStepperIncrement 重命名为 NumberInput.IncrementTrigger

  • NumberInputStepperDecrement 重命名为 NumberInput.DecrementTrigger

  • onChange 属性现为 onValueChange

  • 移除 focusBorderColorerrorBorderColor,考虑改为设置 --focus-color--error-color css 变量。

  • onInvalid 属性现为 onValueInvalid

  • parseformat 属性已被移除,取而代之的是 formatOptions 属性

修改前

¥Before

<NumberInput>
  <NumberInputField />
  <NumberInputStepper>
    <NumberIncrementStepper />
    <NumberDecrementStepper />
  </NumberInputStepper>
</NumberInput>

修改后

¥After

<NumberInput.Root>
  <NumberInput.Input />
  <NumberInput.Control>
    <NumberInput.IncrementTrigger />
    <NumberInput.DecrementTrigger />
  </NumberInput.Control>
</NumberInput.Root>

分隔符

¥Divider

  • 重命名为 Separator

  • 切换到 div 元素以获得更好的布局控制

  • 简化组件以依赖 borderTopWidthborderInlineStartWidth

  • 要可靠地更改宽度,请设置 --divider-border-width CSS 变量。

输入框、选择框、文本框

¥Input, Select, Textarea

  • 移除 invalid 属性,改为将组件封装在 Field 组件中。这允许轻松添加标签、错误文本和星号。

修改前

¥Before

<Input invalid />

修改后

¥After

<Field.Root invalid>
  <Field.Label>Email</Field.Label>
  <Input />
  <Field.ErrorText>This field is required</Field.ErrorText>
</Field.Root>

链接

¥Link

  • 移除 isExternal 属性,改为明确设置 targetrel 属性。

修改前

¥Before

<Link isExternal>Click me</Link>

修改后

¥After

<Link target="_blank" rel="noopener noreferrer">
  Click me
</Link>

按钮

¥Button

  • 移除 isActive 属性,改为传递 data-active 属性。

修改前

¥Before

<Button isActive>Click me</Button>

修改后

¥After

<Button data-active>Click me</Button>

IconButton

  • 移除 icon 属性,改为直接渲染 children 属性。

  • 移除 isRounded 属性,改为使用 borderRadius=full 属性。

旋转器

¥Spinner

  • thickness 属性更改为 borderWidth

  • speed 属性更改为 animationDuration

修改前

¥Before

<Spinner thickness="2px" speed="0.5s" />

修改后

¥After

<Spinner borderWidth="2px" animationDuration="0.5s" />

对话框,抽屉

¥Dialog, Drawer

  • isOpenonChange 属性已被移除,取而代之的是 openonOpenChange 属性

  • blockScrollOnMount 现在是 preventScroll

  • closeOnEsc 现在是 closeOnEscape

  • closeOnOverlayClick 现在是 closeOnInteractOutside

  • initialFocusRef 现在是返回元素的 initialFocusEl 函数

  • finalFocusRef 现在是返回元素的 finalFocusEl 函数

可编辑

¥Editable

  • finalFocusRef 现在是返回元素的 finalFocusEl 函数

  • isDisabled 现在是 disabled

  • onSubmit 现在是 onValueCommit

  • onCancel 现在是 onValueRevert

  • onChange 现在是 onValueChange

  • startWithEditView 现在是 defaultEdit

  • submitOnBlur 替换为 submitMode

FormControl

  • Field 组件替换 FormControl

  • Field.ErrorText 组件替换 FormErrorMessage

修改前:

¥Before:

<FormControl>
  <Input />
  <FormErrorMessage>This field is required</FormErrorMessage>
</FormControl>

修改后:

¥After:

<Field.Root>
  <Input />
  <Field.ErrorText>This field is required</Field.ErrorText>
</Field.Root>

收起

¥Collapse

Collapsible 组件替换。

¥Replace with the Collapsible component.

修改前:

¥Before:

<Collapse in={isOpen} animateOpacity>
  Some content
</Collapse>

修改后:

¥After:

<Collapsible.Root open={isOpen}>
  <Collapsible.Content>Some content</Collapsible.Content>
</Collapsible.Root>

滑块

¥Slider

  • onChange 属性现为 onValueChange

  • onChangeEnd 属性现为 onValueChangeEnd

  • onChangeStart 属性现已移除

  • isReversed 属性现已移除

RangeSlider

现在可以通过传递值数组将其用作单个滑块。

¥Can now be used as a single slider by passing an array of values

修改前:

¥Before:

<RangeSlider defaultValue={[10, 30]}>
  <RangeSliderTrack>
    <RangeSliderFilledTrack />
  </RangeSliderTrack>
  <RangeSliderThumb index={0} />
  <RangeSliderThumb index={1} />
</RangeSlider>

修改后:

¥After:

<Slider.Root defaultValue={[10, 30]}>
  <Slider.Control>
    <Slider.Track>
      <Slider.Range />
    </Slider.Track>
    <Slider.Thumbs />
  </Slider.Control>
</Slider.Root>

表格

¥Table

  • TableContainer 现在是 Table.ScrollArea

  • Td(现称为 Table.ColumnHeaderisNumeric 现为 textAlign="end"

复合组件已略微重命名。

¥The compound component have been renamed slightly.

修改前:

¥Before:

<Table variant="simple">
  <TableCaption>Imperial to metric conversion factors</TableCaption>
  <Thead>
    <Tr>
      <Th>Product</Th>
      <Th>Category</Th>
      <Th isNumeric>Price</Th>
    </Tr>
  </Thead>
  <Tbody>
    {items.map((item) => (
      <Tr key={item.id}>
        <Td>{item.name}</Td>
        <Td>{item.category}</Td>
        <Td isNumeric>{item.price}</Td>
      </Tr>
    ))}
  </Tbody>
  <Tfoot>
    <Tr>
      <Th>Product</Th>
      <Th>Category</Th>
      <Th isNumeric>Price</Th>
    </Tr>
  </Tfoot>
</Table>

修改后:

¥After:

<Table.Root size="sm">
  <Table.Header>
    <Table.Row>
      <Table.ColumnHeader>Product</Table.ColumnHeader>
      <Table.ColumnHeader>Category</Table.ColumnHeader>
      <Table.ColumnHeader textAlign="end">Price</Table.ColumnHeader>
    </Table.Row>
  </Table.Header>
  <Table.Body>
    {items.map((item) => (
      <Table.Row key={item.id}>
        <Table.Cell>{item.name}</Table.Cell>
        <Table.Cell>{item.category}</Table.Cell>
        <Table.Cell textAlign="end">{item.price}</Table.Cell>
      </Table.Row>
    ))}
  </Table.Body>
</Table.Root>

标签

¥Tag

TagLeftIconTagRightIcon 现在是 Tag.StartElementTag.EndElement

¥TagLeftIcon and TagRightIcon are now Tag.StartElement and Tag.EndElement

修改前:

¥Before:

<Tag>
  <TagLeftIcon boxSize="12px" as={AddIcon} />
  <TagLabel>Cyan</TagLabel>
  <TagRightIcon boxSize="12px" as={AddIcon} />
</Tag>

修改后:

¥After:

<Tag.Root>
  <Tag.StartElement>
    <AddIcon />
  </Tag.StartElement>
  <Tag.Label>Cyan</Tag.Label>
  <Tag.EndElement>
    <AddIcon />
  </Tag.EndElement>
</Tag.Root>
  • TagCloseButton 现在是 Tag.CloseTrigger

修改前:

¥Before:

<Tag>
  <TagLabel>Green</TagLabel>
  <TagCloseButton />
</Tag>

修改后:

¥After:

<Tag.Root>
  <Tag.Label>Green</Tag.Label>
  <Tag.CloseTrigger />
</Tag.Root>

警报

¥Alert

  • AlertIcon 现在是 Alert.Indicator

修改前:

¥Before:

<Alert>
  <AlertIcon />
  <AlertTitle>Your browser is outdated!</AlertTitle>
  <AlertDescription>Your Chakra experience may be degraded.</AlertDescription>
</Alert>

修改后:

¥After:

<Alert.Root status="error">
  <Alert.Indicator />
  <Alert.Content>
    <Alert.Title>Invalid Fields</Alert.Title>
    <Alert.Description>
      Your form has some errors. Please fix them and try again.
    </Alert.Description>
  </Alert.Content>
</Alert.Root>
  • 移除 addRole 属性,替换为 role 属性。

骨架

¥Skeleton

  • startColorendColor 属性现在使用 CSS 变量

修改前:

¥Before:

<Skeleton startColor="pink.500" endColor="orange.500" />

修改后:

¥After:

<Skeleton
  css={{
    "--start-color": "colors.pink.500",
    "--end-color": "colors.orange.500",
  }}
/>
  • isLoaded 属性现为 loading

修改前:

¥Before:

<Skeleton isLoaded>
  <span>Chakra ui is cool</span>
</Skeleton>

修改后:

¥After:

<Skeleton loading={false}>
  <span>Chakra ui is cool</span>
</Skeleton>

菜单

¥Menu

  • 现在到处都可以使用复合组件

修改前:

¥Before:

<Menu>
  <MenuButton as={Button} rightIcon={<ChevronDownIcon />}>
    Actions
  </MenuButton>
  <MenuList>
    <MenuItem>Download</MenuItem>
    <MenuItem>Create a Copy</MenuItem>
  </MenuList>
</Menu>

修改后:

¥After:

<Menu.Root>
  <Menu.Trigger asChild>
    <Button>
      Actions
      <ChevronDownIcon />
    </Button>
  </Menu.Trigger>
  <Portal>
    <Menu.Positioner>
      <Menu.Content>
        <Menu.Item value="download">Download</Menu.Item>
        <Menu.Item value="copy">Create a Copy</Menu.Item>
      </Menu.Content>
    </Menu.Positioner>
  </Portal>
</Menu.Root>
  • 现在通过 Menu.Context 访问内部状态,不再通过 render 属性。

修改前:

¥Before:

<Menu>
  {({ isOpen }) => (
    <>
      <MenuButton isActive={isOpen} as={Button} rightIcon={<ChevronDownIcon />}>
        {isOpen ? "Close" : "Open"}
      </MenuButton>
      <MenuList>
        <MenuItem>Download</MenuItem>
        <MenuItem onClick={() => alert("Kagebunshin")}>Create a Copy</MenuItem>
      </MenuList>
    </>
  )}
</Menu>

修改后:

¥After:

<Menu.Root>
  <Menu.Context>
    {(menu) => (
      <Menu.Trigger asChild>
        <Button>
          {menu.open ? "Close" : "Open"}
          <ChevronDownIcon />
        </Button>
      </Menu.Trigger>
    )}
  </Menu.Context>
  <Portal>
    <Menu.Positioner>
      <Menu.Content>
        <Menu.Item value="download">Download</Menu.Item>
        <Menu.Item value="copy" onSelect={() => alert("Kagebunshin")}>
          Create a Copy
        </Menu.Item>
      </Menu.Content>
    </Menu.Positioner>
  </Portal>
</Menu.Root>
  • Menu 上的 isLazy 属性已拆分为 lazyMountMenu.Root 上的 unmountOnExit

  • MenuOptionGroup 现在拆分为 Menu.RadioItemGroupMenu.CheckboxItemGroup,以分别处理状态。

修改前:

¥Before:

<Menu>
  <MenuButton as={Button}>Trigger</MenuButton>
  <MenuList>
    <MenuOptionGroup defaultValue="asc" title="Order" type="radio">
      <MenuItemOption value="asc">Ascending</MenuItemOption>
      <MenuItemOption value="desc">Descending</MenuItemOption>
    </MenuOptionGroup>
    <MenuDivider />
    <MenuOptionGroup title="Country" type="checkbox">
      <MenuItemOption value="email">Email</MenuItemOption>
      <MenuItemOption value="phone">Phone</MenuItemOption>
      <MenuItemOption value="country">Country</MenuItemOption>
    </MenuOptionGroup>
  </MenuList>
</Menu>

修改后:

¥After:

<Menu.Root>
  <Menu.Trigger asChild>
    <Button>Trigger</Button>
  </Menu.Trigger>
  <Portal>
    <Menu.Positioner>
      <Menu.Content minW="10rem">
        <Menu.RadioItemGroup defaultValue="asc">
          <Menu.RadioItem value="asc">Ascending</Menu.RadioItem>
          <Menu.RadioItem value="desc">Descending</Menu.RadioItem>
        </Menu.RadioItemGroup>
        <Menu.CheckboxItemGroup defaultValue={["email"]}>
          <Menu.CheckboxItem value="email">Email</Menu.CheckboxItem>
          <Menu.CheckboxItem value="phone">Phone</Menu.CheckboxItem>
          <Menu.CheckboxItem value="country">Country</Menu.CheckboxItem>
        </Menu.CheckboxItemGroup>
      </Menu.Content>
    </Menu.Positioner>
  </Portal>
</Menu.Root>

工具提示

¥Tooltip

  • closeOnEsc 现已重命名为 closeOnEscape

  • closeOnMouseDown 现在是 closeOnPointerDown

  • Tooltip 上的 placementgutteroffsetarrow 现在包含在 Tooltip.Root 上的 positioning 属性中

修改前:

¥Before:

<Tooltip placement="top" />

修改后:

¥After:

<Tooltip.Root positioning={{ placement: "top" }} />

折叠面板

¥Accordion

  • 以下属性已更改:

    • allowMultiple -> multiple

    • allowToggle -> collapsible

    • index -> value

    • defaultIndex -> defaultValue

修改前:

¥Before:

<Accordion allowMultiple index={[0]} onChange={() => {}} />

修改后:

¥After:

<Accordion multiple value={["0"]} onValueChange={() => {}} />
  • AccordionButton 现在是 Accordion.Trigger

  • AccordionIcon 现在是 Accordion.ItemIndicator

修改前:

¥Before:

<AccordionButton>Section 1 title</AccordionButton>

修改后:

¥After:

<Accordion.Trigger>Section 1 title</Accordion.Trigger>

标签

¥Tabs

  • 组件结构已更改,现在列表和面板上都需要 value 属性。

修改前:

¥Before:

<Tabs>
  <TabList>
    <Tab>One</Tab>
    <Tab>Two</Tab>
    <Tab>Three</Tab>
  </TabList>
  <TabPanels>
    <TabPanel>one!</TabPanel>
    <TabPanel>two!</TabPanel>
    <TabPanel>three!</TabPanel>
  </TabPanels>
</Tabs>

修改后:

¥After:

<Tabs.Root>
  <Tabs.List>
    <Tabs.Trigger value="one">One</Tabs.Trigger>
    <Tabs.Trigger value="two">Two</Tabs.Trigger>
    <Tabs.Trigger value="three">Three</Tabs.Trigger>
  </Tabs.List>
  <Tabs.Content value="one">one!</Tabs.Content>
  <Tabs.Content value="two">two!</Tabs.Content>
  <Tabs.Content value="three">three!</Tabs.Content>
</Tabs.Root>
  • defaultIndexindexonChange 现在分别为 defaultValuevalueonValueChange

修改前:

¥Before:

<Tabs defaultIndex={0} index={0} onChange={(index) => {}} />

修改后:

¥After:

<Tabs defaultValue={0} value={0} onValueChange={({ value }) => {}} />
  • Tabs 上的 isLazy 属性现为 lazyMountTabs.Root 上的 unmountOnExit

修改前:

¥Before:

<Tabs isLazy />

修改后:

¥After:

<Tabs.Root lazyMount unmountOnExit />

显示和隐藏

¥Show and Hide

  • ShowHide 组件已被移除,取而代之的是 hideFromhideBelow

修改前:

¥Before:

<Show below="md">
  This text appears only on screens md and smaller.
</Show>

<Hide below="md">
  This text hides at the "md" value screen width and smaller.
</Hide>

修改后:

¥After:

<Box hideBelow="md">
  This text hides at the "md" value screen width and smaller.
</Box>

<Box hideFrom="md">
  This text appears only on screens md and larger.
</Box>

复选框

¥Checkbox

  • 已重构以使用复合组件

修改前:

¥Before:

<Checkbox defaultChecked>Checkbox</Checkbox>

修改后:

¥After:

<Checkbox.Root defaultChecked>
  <Checkbox.HiddenInput />
  <Checkbox.Control>
    <Checkbox.Indicator />
  </Checkbox.Control>
  <Checkbox.Label>Checkbox</Checkbox.Label>
</Checkbox.Root>

单选按钮组

¥Radio Group

  • 已重构以使用复合组件

修改前:

¥Before:

<RadioGroup defaultValue="2">
  <Radio value="1">Radio</Radio>
  <Radio value="2">Radio</Radio>
</RadioGroup>

修改后:

¥After:

<RadioGroup.Root defaultValue="2">
  <RadioGroup.Item value="1">
    <RadioGroup.ItemHiddenInput />
    <RadioGroup.ItemIndicator />
    <RadioGroup.ItemText />
  </RadioGroup.Item>
</RadioGroup.Root>

按钮属性

¥Button Props

  • isActivedata-active 属性

  • isDisableddisabled

  • isLoadingloading

  • leftIconrightIcon → 作为子元素传递

  • iconSpacing → 已移除(在弹性布局中使用间隙)

  • colorSchemecolorPalette

示例:

¥Example:

// Before
<Button
  isActive={true}
  isDisabled={false}
  isLoading={true}
  leftIcon={<Icon />}
  rightIcon={<Icon />}
  colorScheme="blue"
>
  Submit
</Button>

// After
<Button
  data-active=""
  disabled={false}
  loading={true}
  colorPalette="blue"
>
  <LeftIcon />
  Submit
  <RightIcon />
</Button>

输入框属性

¥Input Props

  • isDisableddisabled

  • isInvalidinvalid

  • isReadOnlyreadOnly

  • isRequiredrequired

  • colorSchemecolorPalette

  • focusBorderColor → 使用 CSS 变量

  • errorBorderColor → 使用 CSS 变量

示例:

¥Example:

// Before
<Input
  isDisabled={false}
  isInvalid={true}
  isReadOnly={false}
  isRequired={true}
  colorScheme="blue"
  focusBorderColor="blue.500"
  errorBorderColor="red.500"
/>

// After
<Input
  disabled={false}
  invalid={true}
  readOnly={false}
  required={true}
  colorPalette="blue"
  style={{
    "--focus-color": "blue.500",
    "--error-color": "red.500"
  }}
/>

复选框属性

¥Checkbox Props

  • isCheckedchecked

  • isDisableddisabled

  • isInvalidinvalid

  • isIndeterminateindeterminate(在指示器上)

  • colorSchemecolorPalette

  • iconColor → 已移除(使用 CSS)

  • iconSize → 已移除(使用 CSS)

  • spacing → 已移除(使用间隙)

示例:

¥Example:

// Before
<Checkbox
  isChecked={true}
  isDisabled={false}
  isInvalid={true}
  isIndeterminate={true}
  colorScheme="blue"
>
  Accept terms
</Checkbox>

// After
<Checkbox.Root
  checked={true}
  disabled={false}
  invalid={true}
  colorPalette="blue"
>
  <Checkbox.Control>
    <Checkbox.Indicator indeterminate={true} />
  </Checkbox.Control>
  <Checkbox.Label>Accept terms</Checkbox.Label>
</Checkbox.Root>

模态窗口到对话框的属性

¥Modal to Dialog Props

  • isOpenopen

  • onCloseonOpenChange(不同签名)

  • isCenteredplacement="center"

  • scrollBehavior → 相同

  • motionPreset → 已更新值(例如,slideInBottomslide-in-bottom

  • closeOnOverlayClickcloseOnInteractOutside

  • closeOnEsccloseOnEscape

  • blockScrollOnMountpreventScroll

  • returnFocusOnCloserestoreFocus

  • initialFocusRefinitialFocusEl(函数)

  • finalFocusReffinalFocusEl(函数)

示例:

¥Example:

// Before
<Modal
  isOpen={isOpen}
  onClose={onClose}
  isCentered={true}
  closeOnOverlayClick={true}
  initialFocusRef={initialRef}
>
  <ModalOverlay />
  <ModalContent>
    <ModalHeader>Title</ModalHeader>
    <ModalBody>Content</ModalBody>
  </ModalContent>
</Modal>

// After
<Dialog.Root
  open={isOpen}
  onOpenChange={(e) => !e.open && onClose()}
  placement="center"
  closeOnInteractOutside={true}
  initialFocusEl={() => initialRef.current}
>
  <Dialog.Backdrop />
  <Dialog.Positioner>
    <Dialog.Content>
      <Dialog.Header>
        <Dialog.Title>Title</Dialog.Title>
      </Dialog.Header>
      <Dialog.Body>Content</Dialog.Body>
    </Dialog.Content>
  </Dialog.Positioner>
</Dialog.Root>

堆叠属性

¥Stack Props

  • spacinggap

  • dividerseparator

  • 其他属性保持不变

示例:

¥Example:

// Before
<Stack
  spacing="4"
  divider={<StackDivider />}
>
  <Box>Item 1</Box>
  <Box>Item 2</Box>
</Stack>

// After
<Stack
  gap="4"
  separator={<Stack.Separator />}
>
  <Box>Item 1</Box>
  <Box>Item 2</Box>
</Stack>

Previous

安装

Next

CLI