频道
bg

Chakra-UI

coding十月 17, 20221mins
Frontend React

Chakra-UI是我用的最好的用的UI库,没有之一。对于UI库的使用,通常来说,我们就是引入它们,然后按照既定的HTML标签和样式书写,对他们的修改或者扩展,主要是对它们主题文件中的变量的修改。而Chakra-UI,比起说是UI库,我更愿意它说是UI框架,因为它拥有极强的扩展能力。

在说Chakra-UI之前,我们首先需要做一些铺垫。

首先是styled-components,它赋予了我们CSS-in-JS的能力,它可以让样式和组件代码保持紧密的联系,使得组件的样式更易于管理和复用。

System UI Theme Specification是一个定义主题对象的规范,它抽象了在一个主题样式中应该抽象出来的style values,scales以及design tokens。

Theme KeyCSS Properties
spacemarginmargin-topmargin-rightmargin-bottommargin-leftpaddingpadding-toppadding-rightpadding-bottompadding-leftgrid-gapgrid-column-gapgrid-row-gap
fontSizesfont-size
colorscolorbackground-colorborder-color
fontsfont-family
fontWeightsfont-weight
lineHeightsline-height
letterSpacingsletter-spacing
sizeswidthheightmin-widthmax-widthmin-heightmax-height
bordersborderborder-topborder-rightborder-bottomborder-left
borderWidthsborder-width
borderStylesborder-style
radiiborder-radius
shadowsbox-shadowtext-shadow
zIndicesz-index
transitionstransition

styled-system是一种定义组件样式的系统,它通过组建的style相关的props来控制组件样式。这些style props通过引用theme objects中定义的token。

下面例子有助于对上述的概念的理解,例如我们有下述的theme objects对象

Javascript

const spacing = {
space: {
px: '1px',
0.5: '0.125rem',
1: '0.25rem',
1.5: '0.375rem',
2: '0.5rem',
2.5: '0.625rem',
3: '0.75rem',
3.5: '0.875rem',
},
}

Javascript

import styled from 'styled-components'
import { space } from './space'
// Add styled-system functions to your component
const Box = styled.div`
${space}
`

通过m属性,可以定义一个margin为 ‘0.5rem’的div(theme.space.2)

bash

<Box m={2} />

本身背后的思想和SASS在主题定义变量,然后在使用的地方引用是来保持样式的整体一致性的思路是一致的。

Chakra-UI是上述思想的实现框架,并且它通过良好的抽象,是的主题具有较好的扩展性。

样式H2

Chakra-UI除了对提供了对上述的theme objects的封装,它的组件通过下述的方式抽象它的样式

bash

const ComponentStyle: ComponentStyleConfig = {
// 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', 'variant' and 'colorScheme'
defaultProps: {
size: '',
variant: '',
colorScheme: '',
},
  • baseStyle定义其基础的样式
  • size定义其不同尺寸下的样式
  • variant定义了其不同变种下的样式
  • colorScheme 定义了其不同颜色模式下的样式

例如下面对一个Button按钮的样式定义

Javascript

const baseStyle = defineStyle({
display: "inline-flex",
appearance: "none",
alignItems: "center",
justifyContent: "center",
userSelect: "none",
position: "relative",
whiteSpace: "nowrap",
verticalAlign: "middle",
outline: "none",
lineHeight: "1.2",
gap: "0.5rem",
borderRadius: "md",
fontWeight: "semibold",
transitionProperty: "common",
transitionDuration: "normal",
})
const variantUnstyled = defineStyle({
bg: "none",
color: "inherit",
display: "inline",
lineHeight: "inherit",
m: "0",
p: "0",
})
const variantGhost = defineStyle({
bg: "transparent",
})
const variants = {
ghost: variantGhost,
unstyled: variantUnstyled,
}
const sizes = {
lg: defineStyle({
h: "12",
minW: "12",
fontSize: "lg",
px: "6",
}),
md: defineStyle({
h: "10",
minW: "10",
fontSize: "md",
px: "4",
}),
sm: defineStyle({
h: "8",
minW: "8",
fontSize: "sm",
px: "3",
}),
xs: defineStyle({
h: "6",
minW: "6",
fontSize: "xs",
px: "2",
}),
}

在使用时,我们可以通过上述的属性以及theme objects中的token来自定义它的样式

Javascript

<Button variant="ghost" size="lg" mx={4} w={20} />

上述的组件样式,Chakra-UI本身封装了一套默认的样式,我们可以通过extendTheme方法来扩展

Javascript

const theme = extendTheme({
components: {
Button: {
...
sizes: {
sm: {
fontSize: 'md'
}
},
variants: {
...
base: {
bg: 'yellow.500',
fontSize: 'md'
},
sm: {
bg: 'teal.500',
fontSize: 'lg'
},
md: {
bg: 'orange.500',
fontSize: 'xl'
},
}
},
},
});

响应式样式H3

Chakra UI可以通过数据语法来定义不同的页面宽度下的样式

Javascript

<Box bg="red.200" w={[300, 400, 500]}>
This is a box
</Box>

这里的300,400,500对应的页面宽度的媒体查询条件是通过breakpoints来定义的

Javascript

const breakpoints = {
base: "0em", // 0px
sm: "30em", // ~480px. em is a relative unit and is dependant on the font size.
md: "48em", // ~768px
lg: "62em", // ~992px
xl: "80em", // ~1280px
"2xl": "96em", // ~1536px
};

意味着,页面在0-480px宽度是,组件的width是sizes token中定义的300的key所对应的值。

SX属性H3

也可以打破theme objects的约束,使用sx属性来定义任意的CSS属性样式

Javascript

<Image
src='http://placekitten.com/200/300'
alt='a kitten'
sx={{ filter: 'blur(8px)' }}
/>

评论


新的评论

匹配您的Gravatar头像

Joen Yu

@2022 JoenYu, all rights reserved. Made with love.