使用高级 Chakra UI 组件更快地构建 💎

了解更多
跳到内容
文档演练场指南博客
赞助商

配方

使用 Chakra 中的配方编写多变体样式。

概述

Chakra 提供了一种编写 CSS-in-JS 的方式,具有更好的性能、开发体验和可组合性。其关键特性之一是能够使用类型安全的运行时 API 创建多变体样式。

一个配方包含以下属性

  • className:要附加到组件的 className
  • base:组件的基础样式
  • variants:组件的不同视觉样式
  • compoundVariants:组件的变体不同组合
  • defaultVariants:组件的默认变体值

定义配方

使用 defineRecipe 标识函数来创建配方。

button.recipe.ts

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

export const buttonRecipe = defineRecipe({
  base: {
    display: "flex",
  },
  variants: {
    visual: {
      solid: { bg: "red.200", color: "white" },
      outline: { borderWidth: "1px", borderColor: "red.200" },
    },
    size: {
      sm: { padding: "4", fontSize: "12px" },
      lg: { padding: "8", fontSize: "24px" },
    },
  },
})

使用配方

有两种方式可以在组件中使用配方

  • 直接在组件中使用 useRecipe
  • 使用 chakra 工厂创建组件(推荐)
信息
RSC 提示:由于它在内部依赖于像 useContextuseInsertionEffect 这样的 React 钩子,因此需要添加 "use client" 指令。

直接在组件中

使用 useRecipe 钩子来获取组件的配方。然后,使用其变体属性调用配方以获取样式。

button.tsx

"use client"

import { chakra, useRecipe } from "@chakra-ui/react"
import { buttonRecipe } from "./button.recipe"

export const Button = (props) => {
  const { visual, size, ...restProps } = props

  const recipe = useRecipe({ recipe: buttonRecipe })
  const styles = recipe({ visual, size })

  return <chakra.button css={styles} {...restProps} />
}

splitVariantProps

请注意,visualsize 属性是如何从要传递给配方的属性中解构出来的。一个更智能的方法是自动将配方属性从组件属性中分离出来。

为此,使用 recipe.splitVariantProps 函数将配方属性从组件属性中分离出来。

button.tsx

"use client"

import { chakra, useRecipe } from "@chakra-ui/react"
import { buttonRecipe } from "./button.recipe"

export const Button = (props) => {
  const recipe = useRecipe({ recipe: buttonRecipe })
  const [recipeProps, restProps] = recipe.splitVariantProps(props)
  const styles = recipe(recipeProps)

  // ...
}

TypeScript

要推断配方变体属性类型,请使用 RecipeVariantProps 类型助手。

button.tsx

import type { RecipeVariantProps } from "@chakra-ui/react"
import { buttonRecipe } from "./button.recipe"

type ButtonVariantProps = RecipeVariantProps<typeof buttonRecipe>

export interface ButtonProps
  extends React.PropsWithChildren<ButtonVariantProps> {}

创建组件

使用 chakra 函数从配方创建组件。

注意:配方也可以内联到 chakra 函数中。

button.tsx

"use client"

import { chakra } from "@chakra-ui/react"
import { buttonRecipe } from "./button.recipe"

export const Button = chakra("button", buttonRecipe)

接下来,使用该组件并向其传递配方属性。

app.tsx

import { Button } from "./button"

const App = () => {
  return (
    <Button visual="solid" size="lg">
      Click Me
    </Button>
  )
}

默认变体

defaultVariants 属性用于设置配方的默认变体值。这在您希望默认应用某个变体时很有用。

button.tsx

"use client"

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

const Button = chakra("button", {
  base: {
    display: "flex",
  },
  variants: {
    visual: {
      solid: { bg: "red.200", color: "white" },
      outline: { borderWidth: "1px", borderColor: "red.200" },
    },
    size: {
      sm: { padding: "4", fontSize: "12px" },
      lg: { padding: "8", fontSize: "24px" },
    },
  },
  defaultVariants: {
    visual: "solid",
    size: "lg",
  },
})

复合变体

使用 compoundVariants 属性定义一组基于其他变体组合应用的变体。

button.tsx

"use client"

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

const button = cva({
  base: {
    display: "flex",
  },
  variants: {
    visual: {
      solid: { bg: "red.200", color: "white" },
      outline: { borderWidth: "1px", borderColor: "red.200" },
    },
    size: {
      sm: { padding: "4", fontSize: "12px" },
      lg: { padding: "8", fontSize: "24px" },
    },
  },
  compoundVariants: [
    {
      size: "small",
      visual: "outline",
      css: {
        borderWidth: "2px",
      },
    },
  ],
})

当您同时使用 size="small"visual="outline" 变体时,compoundVariants 将把 css 属性应用于组件。

app.tsx

<Button size="small" visual="outline">
  Click Me
</Button>

注意事项

由于设计限制,将 compoundVariants 与响应式值一起使用不起作用。

这意味着这样的代码将无法工作

<Button size={{ base: "sm", md: "lg" }} visual="outline">
  Click Me
</Button>

对于这些情况,我们建议渲染组件的多个版本,使用不同的断点,然后根据需要进行隐藏/显示。

主题使用

要以可重用方式使用配方,请将其移动到系统主题并添加到 theme.recipes 属性。

theme.ts

import { createSystem, defaultConfig, defineConfig } from "@chakra-ui/react"
import { buttonRecipe } from "./button.recipe"

const config = defineConfig({
  theme: {
    recipes: {
      button: buttonRecipe,
    },
  },
})

export default createSystem(defaultConfig, config)

TypeScript

使用 CLI 为配方生成类型。

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

然后,在您的组件中导入生成的类型。

button.tsx

import type { RecipeVariantProps } from "@chakra-ui/react"
import { buttonRecipe } from "./button.recipe"

type ButtonVariantProps = RecipeVariantProps<typeof buttonRecipe>

export interface ButtonProps
  extends React.PropsWithChildren<ButtonVariantProps> {}

更新代码

如果您直接在组件中使用配方,请更新 useRecipe 以使用 key 属性从主题中获取配方。

button.tsx

const Button = () => {
-  const recipe = useRecipe({ recipe: buttonRecipe })
+  const recipe = useRecipe({ key: "button" })
  // ...
}

上一页

语义令牌

下一页

插槽配方