React UI 组件库 Chakra UI - 04全局组件样式配置

全局组件样式配置

官方文档:Component Style

基础样式和修改器样式

大多数组件的样式由基础样式和修改器样式组成,修改器样式根据某些特性或状态更改其大小或视觉样式。

  • 基础样式:默认样式
  • 修改器样式:可以根据 props 切换的样式
    • 常用的修改器样式包括:
      • Size:组件的尺寸(例如 small medium large)
        • 根据 props.size 切换
      • Variant:组件的视觉风格(例如 outline、solid、ghost)
        • 根据 props.variant 切换
      • Color scheme:组件的配色方案
        • 根据 props.colorSchmeme 切换
      • Color mode:组件根据当前颜色模式更改其视觉样式

样式配置对象

一个样式配置对象可以配置以下属性:

  • baseStyle:基础样式对象
  • sizes:为每个尺寸设置样式对象
  • variants:为每个风格设置样式对象
  • defaultProps:默认样式配置,可配置的属性:
    • size:尺寸
    • variant:风格
    • colorScheme:配色方案
    • colorMode:强制的颜色模式
  • parts:用于配置复合组件的样式

设置样式的方式有两种:

  • 对象字面量
  • 函数
    • 函数接收组件的 props 作为参数,最终返回一个样式对象
    • props 包含:
      • defaultProps 配置的属性
      • 使用组件时手动设置的属性
      • 主题对象 theme
      • 颜色模式 colorMode

一个组件的样式配置对象示例:

const Button = {
     
  // 基础样式
  baseStyle: {
     
    // 可以使用样式属性配置
    fontWeight: 'bold',
    borderRadius: 'base'
  },
  // 尺寸样式(注意是带`s`的复数名称)
  sizes: {
     
    // 修改已有的尺寸样式
    xs: {
     
      h: '20px'
      fontSize: "12px",
    },
    // 新增一个尺寸样式
    sl: {
     
      h: "56px",
      fontSize: "lg",
      px: "32px",
    }
  },
  // 风格样式(注意是带`s`的复数名称)
  variants: {
     
    // 使用函数定义样式对象
    solid: props => ({
     
    	// 根据 colorScheme 生成边线颜色
      borderColor: props.colorScheme === 'teal' ? 'blue' : 'black',
      // 根据 colorMode 生成背景色
      bgColor: props.colorMode === 'dark' ? 'white' : 'black'
    }),
  },
  // 默认 props
  defaultProps: {
     
    // 默认尺寸(注意不带`s`)
    size: 'sl',
    // 默认风格(注意不带`s`)
    variant: 'solid',
    // 默认配色风格
    colorScheme: 'teal',
    // 强制颜色模式(配置后 `props.colorMode` 将不会改变)
    colorMode: 'dark'
  }
}

Chakra 组件样式配置

通过主题对象的 components 属性修改或扩展 Chakra 组件的全局样式配置。

通常创建一个 theme 目录管理主题配置:

 theme
   index.js  # 主题主入口
   components	# 组件样式配置
     button.js  # Button 按钮的样式配置
// theme/components/button.js
const Button = {
     
  baseStyle: {
     
    px: '20px',
    py: '10px'
  },
  sizes: {
     
    small: {
     
      fontSize: '14px',
    },
    big: {
     
      fontSize: '30px'
    }
  }
}

export default Button

// theme/index.js
import {
      extendTheme } from '@chakra-ui/react'
import Button from './components/button'

const theme = extendTheme({
     
  components: {
     
    Button
  }
})

export default theme

// index.js
import React from 'react'
import ReactDOM from 'react-dom'
import App from './App'
import {
      ChakraProvider } from '@chakra-ui/react'
import theme from './theme'

ReactDOM.render(
  <React.StrictMode>
    <ChakraProvider theme={
     theme}>
      <App />
    </ChakraProvider>
  </React.StrictMode>,
  document.getElementById('root')
)

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

function App() {
     
  return (
    <div>
      <Button size="xs">默认配置的 xs 尺寸</Button>
      <Button size="small">自定义的 small 尺寸</Button>
      <Button size="big">自定义的 big 尺寸</Button>
    </div>
  )
}

export default App

自定义组件样式配置

在主题中扩展自定义组件的样式配置需要做几件事情:

  1. 像 Chakra 组件一样将样式配置对象扩展到主题对象,一般 key 设置为组件名
  2. 在组件中使用 Chakra 组件包裹
  3. 在组件中调用钩子函数获取样式配置,传递给 Chakra 组件的 __css 属性
    • useStyleConfig(themeKey, props) 钩子函数用于获取主题对象中组件的样式配置
      • 返回一个样式对象,用于传递给 Chakra 组件__css 属性
      • __css 属性设置的样式优先级低于手动通过组件的样式属性设置的样式
      • themeKeytheme.components 对象中的对应组件的 key
      • props:配置默认方案
// theme/components/content.js
// 文章内容样式配置

const content = {
     
  baseStyle: {
     
    bgColor: 'gray.200',
    mt: '40px',
    mx: 'auto'
  },
  sizes: {
     
    small: {
     
      fontSize: '12px',
      lineHeight: '18px',
      w: '30%',
      p: '10px'
    },
    large: {
     
      fontSize: '20px',
      lineHeight: '36px',
      w: '80%',
      p: '20px'
    }
  },
  variants: {
     
    solid: {
     
      border: '1px solid',
      borderColor: 'gray.800'
    },
    card: {
     
      boxShadow: 'md'
    }
  },
  defaultProps: {
     
    size: 'large',
    variant: 'solid'
  }
}

export default content

// theme/index.js
import {
      extendTheme } from '@chakra-ui/react'
import Content from './components/content'

const theme = extendTheme({
     
  components: {
     
    Content
  }
})

export default theme

// components/Content.js
// 文章内容组件
import {
      Box, useStyleConfig } from '@chakra-ui/react'

function Content(props) {
     
  const {
      children, size, variant } = props

  const styles = useStyleConfig('Content', {
     
    size: size,
    variant: variant
  })

  return <Box __css={
      styles }>{
      children }</Box>
}

export default Content

// App.js
import Content from './components/Content'

function App() {
     
  return (
    <>
      <Content size="small" variant="card">这是用于展示文章内容的 Content 组件</Content>
    </>
  )
}

export default App

复合组件样式配置

上面是设置 single part components(单部分组件) 的样式配置,如果一个组件由多个组件组成,就称为 multipart components(多部份组件或复合组件)

复合组件设置样式配置与单个组件类似,主要区别是:

  1. 需要在样式配置对象中的 parts 属性中定义每个部分的 part key。
    • 可以是组件名称,或其它自定义的 key
  2. 需要为每个part 提供 baseStylesizesvariants
  3. 使用 useMultiStyleConfig 钩子函数,获取复合组件的样式配置对象,
    • useMultiStyleConfig 接收的参数与 useStyleConfig 一样
    • 它返回一个包含每个 part 的样式配置的对象
    • 使用时向对应的单部分组件传递对应的 __css
  4. 也可以在复合组件的最外层,使用 StylesProvider 组件向上下文共享样式配置对象
    • 下级组件通过 useStyles 钩子函数获取上下文中的样式配置对象

复合组件示例

// components/Article.js
// 文章复合组件
import {
      Box, Heading } from '@chakra-ui/react'

// 复合组件
function Article(props) {
     
  const {
      title, content } = props
  return (
    <Box>
      <Heading>{
     title}</Heading>
      <Box>{
     content}</Box>
    </Box>
  )
}

export default Article

// App.js
import Article from './components/Article'

function App() {
     
  return <Article title="文章标题" content="文章内容" />
}

export default App

样式配置

// theme/components/article.js
// 文章样式配置

const article = {
     
  parts: ['article', 'title', 'content'],
  baseStyle: {
     
    article: {
     
      mt: '40px',
      mx: 'auto'
    },
    title: {
     
      textAlign: 'center',
      fontFamily: 'Microsoft YaHei'
    },
    content: {
     
      fontFamily: 'sans-serif'
    }
  },
  sizes: {
     
    small: {
     
      article: {
     
        w: '50%',
        p: '5px'
      },
      title: {
     
        my: '10px'
      },
      content: {
     
        lineHeight: '1.2em'
      }
    },
    large: {
     
      article: {
     
        w: '80%',
        p: '20px'
      },
      title: {
     
        my: '20px'
      },
      content: {
     
        lineHeight: '1.8em'
      }
    }
  },
  variants: {
     
    solid: {
     
      article: {
     
        border: '1px solid',
        borderColor: 'gray.800'
      }
    },
    card: {
     
      article: {
     
        boxShadow: 'md',
      }
    }
  },
  defaultProps: {
     
    size: 'large',
    variant: 'solid'
  }
}

export default article

应用到组件

// components/Article.js
// 文章复合组件
import {
      Box, Heading, useMultiStyleConfig } from '@chakra-ui/react'

// 复合组件
function Article(props) {
     
  const {
      title, content } = props
  const styles = useMultiStyleConfig('Article', {
     
    variant: 'card'
  })

  return (
    <Box __css={
     styles.article}>
      <Heading __css={
     styles.title}>{
     title}</Heading>
      <Box __css={
     styles.content}>{
     content}</Box>
    </Box>
  )
}

export default Article

使用上下文组件的方式

// App.js
import {
      StylesProvider, useMultiStyleConfig } from '@chakra-ui/react'
import Article from './components/Article'

function App() {
     
  const styles = useMultiStyleConfig('Article', {
     
    variant: 'card'
  })
  return (
    <StylesProvider value={
     styles}>
    	<Article title="文章标题" content="文章内容"></Article>
		</StylesProvider>
  )
}

export default App

// components/Article.js
// 文章复合组件
import {
      Box, Heading, useStyles } from '@chakra-ui/react'

// 复合组件
function Article(props) {
     
  const {
      title, content } = props
  const styles = useStyles()

  return (
    <Box __css={
     styles.article}>
      <Heading __css={
     styles.title}>{
     title}</Heading>
      <Box __css={
     styles.content}>{
     content}</Box>
    </Box>
  )
}

export default Article

你可能感兴趣的:(react)