我使用 Chakra-Ui 至今学到的东西 结论

2025-06-04

我使用 Chakra-Ui 至今学到的东西

结论

当我完成为一个项目构建设计系统(或其中的一部分)时,在开始编码之前出现了一个重要的问题:我应该使用哪个库来设置组件的样式?

最近,我一直在使用 styled-components,但我想尝试一下现在流行的:Tailwind CSS 或 Chakra-Ui。

在观看了一些视频并了解了两者的代码后,我决定使用 Chakra-Ui。

因此,我将在这篇文章中分享我过去两天使用 Chakra-Ui 的体验。希望它能帮助那些刚开始使用 Chakra-Ui 库的人。

1. 创建自定义主题轻而易举

Chakra-Ui 默认自带主题,但我们可以自定义主题,使其更贴合我们的设计。自从我创建了一套设计系统后,我就开始尝试使用 Chakra 了。

主题对象是我们定义应用程序的调色板、类型比例、字体堆栈、边框半径值等的地方。所有 Chakra 组件都从这个默认主题继承。

在默认主题的基础上,我们可以扩展和覆盖 token,也可以为主题添加新值。自定义主题非常简单:

1)扩展它extendTheme


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

const customTheme = extendTheme({
    colors: {
        lightGray: {
            default: '#C4C4C4',
            hover: '#EEEEEE',
            disabled: '#9E9E9E'
        }
    },
    // I'm just adding one more fontSize than the default ones
    fontSizes: {
        xxs: '0.625rem'
    },
    // I'm creating a new space tokens since the default is represented with numbers
    space: {
        xs: '0.25rem',
        sm: '0.5rem',
        md: '1rem',
        lg: '1.5rem',
        xl: '2rem',
        xxl: '3rem',
    }
})

export default customTheme
Enter fullscreen mode Exit fullscreen mode

2)传递给ChakraProvider

import customTheme from './theme'

<ChakraProvider theme={customTheme}>
  <App />
</ChakraProvider>
Enter fullscreen mode Exit fullscreen mode

3)使用方法:

import customTheme from './theme'

const BoxWithText= ({ text }) => (
  <Box padding='xs' borderRadius='lg'>
    <Text>{text}</Text>
  </Box>
)
Enter fullscreen mode Exit fullscreen mode

2. 创建组件变体可以更轻松地实现设计系统

除了自定义主题标记,我们还可以自定义组件样式。

Chakra 组件样式具有特定的 API,组件样式由以下部分组成:

  • baseStyle,组件的默认样式
  • sizes,表示组件不同尺寸的样式
  • variants,代表不同视觉变体的样式
  • defaultProps,可选,定义默认值sizevariant

从文档来看,组件样式是这样的:

const ComponentStyle = {
  // style object for base or default style
  baseStyle: {},
  // styles for different sizes ("sm", "md", "lg")
  sizes: {},
  // styles for different visual variants ("outline", "solid")
  variants: {},
  // default values for `size` and `variant`
  defaultProps: {
    size: "",
    variant: "",
  },
}
Enter fullscreen mode Exit fullscreen mode

由于每个组件都支持自定义,我们可以为它们创建变体,以匹配组件的预定义样式。例如,在设计系统中,您可以为字体设置不同的变体,以显示不同的字体大小、字体粗细等。按钮、输入框等组件也是如此。

通过变体,我们可以为这些组件创建预定义样式:

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

const customTheme = extendTheme({
    components: {
        Heading: {
            variants: {
                h1: {
                    fontSize: '4xl', fontWeight: 'bold'
                },
                h2: {
                    fontSize: '3xl', fontWeight: 'bold'
                }
            }
        },
        Text: {
            variants: {
                subtitle: {
                    fontSize: 'xl', fontWeight: 'medium'
                },
                body: {
                    fontSize: 'md', fontWeight: 'medium'
                }
              }
            }
        }
})

export default customTheme
Enter fullscreen mode Exit fullscreen mode

并在我们的代码中使用它:


const Badge = ({ text }) => (
  <Box padding='xs' borderRadius='lg' w='max-content'>
    <Text variant='bodyExtraSmall'>{text}</Text>
  </Box>
)

Enter fullscreen mode Exit fullscreen mode

3. 目前与 Storybook 的集成还不太顺利

在我刚开始使用 Chakra-Ui 时,我遇到的一个痛点是尝试使用 Storybook 来展示我创建的组件。在我的工作流程中,我总是创建组件及其对应的 Story,以便更容易查看不同的样式并创建组件库。

然而,当我用 Chakra 组件创建故事并检查 Storybook 时,它并没有加载我用 Chakra 制作的任何样式。一开始我很沮丧,但多亏了别人提出的一个问题,我才得以让它正常工作。

要修复该问题,您可以:

1)修改文件夹main.js内的文件.storybook以匹配webpackFinalChakra 使用的配置:

const path = require("path");
const toPath = (_path) => path.join(process.cwd(), _path);

module.exports = {
  stories: ["../src/**/*.stories.mdx", "../src/**/*.stories.@(js|jsx|ts|tsx)"],
  addons: [
    "@storybook/addon-links",
    "@storybook/addon-essentials",
    "@storybook/preset-create-react-app",
  ],
  webpackFinal: async (config) => {
    return {
      ...config,
      resolve: {
        ...config.resolve,
        alias: {
          ...config.resolve.alias,
          "@emotion/core": toPath("node_modules/@emotion/react"),
          "emotion-theming": toPath("node_modules/@emotion/react"),
        },
      },
    };
  },
};
Enter fullscreen mode Exit fullscreen mode

ChakraProvider2)用文件中的以下内容包装故事装饰器preview.js

import React from "react"
import { ChakraProvider } from '@chakra-ui/react'
import theme from '../src/theme'

export const parameters = {
  actions: { argTypesRegex: "^on[A-Z].*" },
}

const withChakra = (StoryFn) => {

  return (
    <ChakraProvider theme={theme}>
      <StoryFn />
    </ChakraProvider>
  )
}

export const decorators = [withChakra]
Enter fullscreen mode Exit fullscreen mode

这是一个临时的解决方法,我相信很快就能解决,因为他们已经在着手解决这个问题了:)

4. 我们不能为 Box 创建变体,但我们可以使用图层样式或文本样式

我遇到的另一个“问题”是当我尝试为组件创建变体时Box。我想创建不同类型的,这样在将它们插入到组件中时,Badges我就可以简单地选择它们。我的徽章由一个内部包含一个的组件组成,代码我在前面的代码片段中已经展示过了。variantBoxText

然而,在发现这个问题之后,我明白了,根据设计,Box由于它是一个通用组件,所以无法接收主题中的变体,它代表一个div

为了解决这个问题,您可以使用useStyleConfig或使用textStylelayerStyle道具,文档在这里

这两个 props 的作用是避免重复特定的文本和图层属性,并帮助我们保持组件的有序性和一致性。它们允许我们保存样式属性,以便在其他组件中重复使用,并将相应的 prop 传递给组件。

由于我只需要根据我想要的类型更改背景颜色和边框Badge,所以我使用了图层样式。

要解决这个问题:
1)使用新的扩展主题layerStyles

const customTheme = extendTheme({
    layerStyles: {
      defaultBadge: { bg:'lightGray.default' },
      outlinedBadge: { bg:'transparent', border: '1px solid #000000' },
      whiteBadge: { bg:'#FFFFFF' }
    }
})
Enter fullscreen mode Exit fullscreen mode

2)在组件中使用它:

const Badge = ({ text }) => (
  <Box layerStyle=`outlinedBadge` padding='xs' borderRadius='lg' w='max-content'>
    <Text variant='bodyExtraSmall'>{text}</Text>
  </Box>
)
Enter fullscreen mode Exit fullscreen mode

结论

暂时就这些。希望您在开始使用 Chakra-Ui 时也能获得一些建议。如果我发现更多有趣的观点和经验可以分享,我可能会再写一篇文章 :)

如果觉得有用,请点个❤️,或者如果你还有更多想补充的,欢迎留言。
另外,我们也欢迎在推特上交流:)

文章来源:https://dev.to/carlosrafael22/what-i-ve-learned-with-chakra-ui-so-far-4f5e
PREV
基于线的截断方法
NEXT
在 React 函数式组件中使用 refs(一)- useRef + 回调 ref 1. 什么是 refs? 2. 在同一个 React 组件中访问 DOM 节点 3. 访问动态添加的 DOM 元素 4. 结论 5. 参考