样式系统

语义化令牌

在应用中使用语义化令牌进行设计决策。

概述

语义化令牌是专门用于特定上下文的令牌。一个语义化令牌包含以下属性:

  • value:令牌的值,或对现有令牌的引用。
  • description:可选的说明,描述该令牌可用于什么场景。

定义语义化令牌

在大多数情况下,语义化令牌的值会引用某个现有令牌。要在语义化令牌中引用值,请使用 令牌引用 {} 语法。

tsx
import { createSystem, defaultConfig, defineConfig } from "@chakra-ui/react"

const config = defineConfig({
  theme: {
    tokens: {
      colors: {
        red: { value: "#EE0F0F" },
      },
    },
    semanticTokens: {
      colors: {
        danger: { value: "{colors.red}" },
      },
    },
  },
})

export default createSystem(defaultConfig, config)

使用语义化令牌

定义语义化令牌之后,运行 Chakra CLI 生成主题类型。关于如何在 postinstall、CI 和 monorepo 中运行 typegen,参见 CLI 文档

bash
npx @chakra-ui/cli typegen ./src/theme.ts

这会在编辑器中为你的令牌提供自动补全:

tsx
<Box color="danger">Hello World</Box>

条件令牌

语义化令牌还可以根据条件(如亮色和暗色模式)改变取值。

例如,如果你希望某个颜色能根据亮色或暗色模式自动改变:

tsx
import { createSystem, defaultConfig, defineConfig } from "@chakra-ui/react"

const config = defineConfig({
  theme: {
    semanticTokens: {
      colors: {
        danger: {
          value: { base: "{colors.red}", _dark: "{colors.darkred}" },
        },
        success: {
          value: { base: "{colors.green}", _dark: "{colors.darkgreen}" },
        },
      },
    },
  },
})

export default createSystem(defaultConfig, config)
提示
语义化令牌中使用的条件必须是 at-rule 或父选择器 条件

语义化令牌嵌套

语义化令牌可以嵌套以创建令牌层级,当你想将令牌分组时这会很有用。

提示
使用 DEFAULT 键来定义嵌套令牌的默认值。
tsx
import { createSystem, defaultConfig, defineConfig } from "@chakra-ui/react"

const config = defineConfig({
  theme: {
    semanticTokens: {
      colors: {
        bg: {
          DEFAULT: { value: "{colors.gray.100}" },
          primary: { value: "{colors.teal.100}" },
          secondary: { value: "{colors.gray.100}" },
        },
      },
    },
  },
})

export default createSystem(defaultConfig, config)

这样你就可以通过以下方式使用 bg 令牌:

tsx
<Box bg="bg">
  <Box bg="bg.primary">Hello World</Box>
  <Box bg="bg.secondary">Hello World</Box>
</Box>

在配方中使用

语义化令牌可以直接用于配方定义中,通过名称引用即可。

tsx
import { defineRecipe } from "@chakra-ui/react"

const cardRecipe = defineRecipe({
  base: {
    bg: "bg.subtle", // 语义化令牌
    color: "fg", // 语义化令牌
    borderColor: "border",
  },
})