迁移到 v3
如何从 Chakra UI v2.x 迁移到 v3.x
步骤
¥Steps
所需的最低 Node 版本为 Node.20.x
更新软件包
¥Update Packages
删除未使用的包:@emotion/styled
和 framer-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
重构自定义主题
¥Refactor Custom Theme
将你的自定义主题移至专用的 theme.js
或 theme.ts
文件。使用 createSystem
和 defaultConfig
配置你的主题。
¥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 此处 的信息。
更新 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 中的 ChakraProvider
和 next-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
-
ColorModeProvider
和useColorMode
已被移除,取而代之的是next-themes
-
LightMode
、DarkMode
和ColorModeScript
组件已被移除。现在你必须使用className="light"
或className="dark"
来强制主题。 -
useColorModeValue
已从next-themes
中移除,取而代之的是useTheme
我们通过 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-use
和 usehooks-ts
。
¥We removed the hooks package in favor of using dedicated, robust libraries like
react-use
and usehooks-ts
我们现在仅提供 useBreakpointValue
、useCallbackRef
、useDisclosure
、useControllableState
和 useMediaQuery
钩子函数。
¥The only hooks we ship now are useBreakpointValue
, useCallbackRef
,
useDisclosure
, useControllableState
and useMediaQuery
.
样式配置
¥Style Config
我们删除了 styleConfig
和 multiStyleConfig
概念,转而使用配方和插槽配方。此模式的灵感来自 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-react
或 react-icons
。
¥Removed @chakra-ui/icons
package. Prefer to use lucide-react
or
react-icons
instead.
Storybook 插件
¥Storybook Addon
我们已移除 Storybook 插件,转而使用 @storybook/addon-themes
和 withThemeByClassName
助手。
¥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
属性设置为initialFocusEl
到Dialog.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
solid
、contrast
、fg
、muted
、subtle
、emphasized
和focusRing
颜色键
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
渐变样式属性简化为 gradient
、gradientFrom
和 gradientTo
属性。这降低了解析渐变字符串的运行时性能成本,并允许更好的类型推断。
¥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
属性,转而使用 textStyle
或 layerStyles
。
¥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
属性。 -
移除
isOpen
和onClose
属性,改为使用open
和onOpenChange
属性。
头像
¥Avatar
-
移除
max
属性,以便用户空间控制。 -
删除多余的标签部分
-
将图片相关属性移至
Avatar.Image
组件 -
将后备图标移至
Avatar.Fallback
组件 -
将
name
属性移至Avatar.Fallback
组件
门户
¥Portal
-
移除
appendToParentPortal
属性,以便使用containerRef
属性。 -
删除
PortalManager
组件
进度
¥Progress
-
现在可以使用带有
Progress.Root
、Progress.Track
和Progress.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-height
和collapse-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
-
将
value
和defaultValue
更改为使用string[]
而不是string
-
onChange
属性现为onValueChange
-
添加新的
PinInput.Control
和PinInput.Label
组件 -
PinInput.Root
现在默认渲染div
元素。考虑与Stack
或Group
结合使用以获得更好的布局控制。 -
onComplete
属性现为onValueComplete
NumberInput
-
将
NumberInputStepper
重命名为NumberInput.Control
-
将
NumberInputStepperIncrement
重命名为NumberInput.IncrementTrigger
-
将
NumberInputStepperDecrement
重命名为NumberInput.DecrementTrigger
-
onChange
属性现为onValueChange
-
移除
focusBorderColor
和errorBorderColor
,考虑改为设置--focus-color
和--error-color
css 变量。 -
onInvalid
属性现为onValueInvalid
-
parse
和format
属性已被移除,取而代之的是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
元素以获得更好的布局控制 -
简化组件以依赖
borderTopWidth
和borderInlineStartWidth
。 -
要可靠地更改宽度,请设置
--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
属性,改为明确设置target
和rel
属性。
修改前
¥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
-
isOpen
和onChange
属性已被移除,取而代之的是open
和onOpenChange
属性 -
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.ColumnHeader
)isNumeric
现为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
TagLeftIcon
和 TagRightIcon
现在是 Tag.StartElement
和 Tag.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
startColor
和endColor
属性现在使用 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
属性已拆分为lazyMount
和Menu.Root
上的unmountOnExit
-
MenuOptionGroup
现在拆分为Menu.RadioItemGroup
和Menu.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
上的placement
、gutter
、offset
和arrow
现在包含在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>
defaultIndex
、index
和onChange
现在分别为defaultValue
、value
和onValueChange
修改前:
¥Before:
<Tabs defaultIndex={0} index={0} onChange={(index) => {}} />
修改后:
¥After:
<Tabs defaultValue={0} value={0} onValueChange={({ value }) => {}} />
Tabs
上的isLazy
属性现为lazyMount
,Tabs.Root
上的unmountOnExit
修改前:
¥Before:
<Tabs isLazy />
修改后:
¥After:
<Tabs.Root lazyMount unmountOnExit />
显示和隐藏
¥Show and Hide
Show
和Hide
组件已被移除,取而代之的是hideFrom
和hideBelow
修改前:
¥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
-
isActive
→data-active
属性 -
isDisabled
→disabled
-
isLoading
→loading
-
leftIcon
和rightIcon
→ 作为子元素传递 -
iconSpacing
→ 已移除(在弹性布局中使用间隙) -
colorScheme
→colorPalette
示例:
¥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
-
isDisabled
→disabled
-
isInvalid
→invalid
-
isReadOnly
→readOnly
-
isRequired
→required
-
colorScheme
→colorPalette
-
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
-
isChecked
→checked
-
isDisabled
→disabled
-
isInvalid
→invalid
-
isIndeterminate
→indeterminate
(在指示器上) -
colorScheme
→colorPalette
-
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
-
isOpen
→open
-
onClose
→onOpenChange
(不同签名) -
isCentered
→placement="center"
-
scrollBehavior
→ 相同 -
motionPreset
→ 已更新值(例如,slideInBottom
→slide-in-bottom
) -
closeOnOverlayClick
→closeOnInteractOutside
-
closeOnEsc
→closeOnEscape
-
blockScrollOnMount
→preventScroll
-
returnFocusOnClose
→restoreFocus
-
initialFocusRef
→initialFocusEl
(函数) -
finalFocusRef
→finalFocusEl
(函数)
示例:
¥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
-
spacing
→gap
-
divider
→separator
-
其他属性保持不变
示例:
¥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>