我使用 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
2)传递给ChakraProvider
:
import customTheme from './theme'
<ChakraProvider theme={customTheme}>
<App />
</ChakraProvider>
3)使用方法:
import customTheme from './theme'
const BoxWithText= ({ text }) => (
<Box padding='xs' borderRadius='lg'>
<Text>{text}</Text>
</Box>
)
2. 创建组件变体可以更轻松地实现设计系统
除了自定义主题标记,我们还可以自定义组件样式。
Chakra 组件样式具有特定的 API,组件样式由以下部分组成:
baseStyle
,组件的默认样式sizes
,表示组件不同尺寸的样式variants
,代表不同视觉变体的样式defaultProps
,可选,定义默认值size
或variant
。
从文档来看,组件样式是这样的:
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: "",
},
}
由于每个组件都支持自定义,我们可以为它们创建变体,以匹配组件的预定义样式。例如,在设计系统中,您可以为字体设置不同的变体,以显示不同的字体大小、字体粗细等。按钮、输入框等组件也是如此。
通过变体,我们可以为这些组件创建预定义样式:
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
并在我们的代码中使用它:
const Badge = ({ text }) => (
<Box padding='xs' borderRadius='lg' w='max-content'>
<Text variant='bodyExtraSmall'>{text}</Text>
</Box>
)
3. 目前与 Storybook 的集成还不太顺利
在我刚开始使用 Chakra-Ui 时,我遇到的一个痛点是尝试使用 Storybook 来展示我创建的组件。在我的工作流程中,我总是创建组件及其对应的 Story,以便更容易查看不同的样式并创建组件库。
然而,当我用 Chakra 组件创建故事并检查 Storybook 时,它并没有加载我用 Chakra 制作的任何样式。一开始我很沮丧,但多亏了别人提出的一个问题,我才得以让它正常工作。
要修复该问题,您可以:
1)修改文件夹main.js
内的文件.storybook
以匹配webpackFinal
Chakra 使用的配置:
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"),
},
},
};
},
};
ChakraProvider
2)用文件中的以下内容包装故事装饰器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]
这是一个临时的解决方法,我相信很快就能解决,因为他们已经在着手解决这个问题了:)
4. 我们不能为 Box 创建变体,但我们可以使用图层样式或文本样式
我遇到的另一个“问题”是当我尝试为组件创建变体时Box
。我想创建不同类型的,这样在将它们插入到组件中时,Badges
我就可以简单地选择它们。我的徽章由一个内部包含一个的组件组成,代码我在前面的代码片段中已经展示过了。variant
Box
Text
然而,在发现这个问题之后,我明白了,根据设计,Box
由于它是一个通用组件,所以无法接收主题中的变体,它代表一个div
。
为了解决这个问题,您可以使用useStyleConfig
或使用textStyle
或layerStyle
道具,文档在这里。
这两个 props 的作用是避免重复特定的文本和图层属性,并帮助我们保持组件的有序性和一致性。它们允许我们保存样式属性,以便在其他组件中重复使用,并将相应的 prop 传递给组件。
由于我只需要根据我想要的类型更改背景颜色和边框Badge
,所以我使用了图层样式。
要解决这个问题:
1)使用新的扩展主题layerStyles
:
const customTheme = extendTheme({
layerStyles: {
defaultBadge: { bg:'lightGray.default' },
outlinedBadge: { bg:'transparent', border: '1px solid #000000' },
whiteBadge: { bg:'#FFFFFF' }
}
})
2)在组件中使用它:
const Badge = ({ text }) => (
<Box layerStyle=`outlinedBadge` padding='xs' borderRadius='lg' w='max-content'>
<Text variant='bodyExtraSmall'>{text}</Text>
</Box>
)
结论
暂时就这些。希望您在开始使用 Chakra-Ui 时也能获得一些建议。如果我发现更多有趣的观点和经验可以分享,我可能会再写一篇文章 :)
如果觉得有用,请点个❤️,或者如果你还有更多想补充的,欢迎留言。
另外,我们也欢迎在推特上交流:)