组件

Button 按钮

用于触发一个动作或事件。

用法

tsx
import { Button, ButtonGroup } from "@chakra-ui/react"
tsx
<Button>点击我</Button>

示例

尺寸

使用 size prop 可以更改按钮的尺寸。

tsx
export const ButtonWithSizes = () => {
  return (
    <HStack wrap="wrap" gap="6">
      <Button size="xs">Button (xs)</Button>
      <Button size="sm">Button (sm)</Button>
      <Button size="md">Button (md)</Button>
      <Button size="lg">Button (lg)</Button>
      <Button size="xl">Button (xl)</Button>
    </HStack>
  )
}

变体

使用 variant prop 可以更改按钮的视觉风格。

tsx
export const ButtonWithVariants = () => {
  return (
    <HStack wrap="wrap" gap="6">
      <Button variant="solid">Solid</Button>
      <Button variant="subtle">Subtle</Button>
      <Button variant="surface">Surface</Button>
      <Button variant="outline">Outline</Button>
      <Button variant="ghost">Ghost</Button>
      <Button variant="plain">Plain</Button>
    </HStack>
  )
}

图标

在按钮内使用图标。

tsx
export const ButtonWithIcons = () => {
  return (
    <HStack>
      <Button colorPalette="teal" variant="solid">
        <RiMailLine /> 发送邮件
      </Button>
      <Button colorPalette="teal" variant="outline">
        联系我们 <RiArrowRightLine />
      </Button>
    </HStack>
  )
}

import { Button, HStack } from "@chakra-ui/react"
import { RiArrowRightLine, RiMailLine } from "react-icons/ri"

颜色

使用 colorPalette prop 可以更改按钮的颜色。

gray

red

orange

yellow

green

teal

blue

cyan

purple

pink

tsx
export const ButtonWithColors = () => {
  return (
    <Stack gap="2" align="flex-start">
      {colorPalettes.map((colorPalette) => (
        <Stack align="center" key={colorPalette} direction="row" gap="10">
          <Text minW="8ch">{colorPalette}</Text>
          <Button colorPalette={colorPalette}>Button</Button>
          <Button colorPalette={colorPalette} variant="outline">
            Button
          </Button>
          <Button colorPalette={colorPalette} variant="surface">
            Button
          </Button>
          <Button colorPalette={colorPalette} variant="subtle">
            Button
          </Button>
        </Stack>
      ))}
    </Stack>
  )
}

import { colorPalettes } from "compositions/lib/color-palettes"

禁用

使用 disabled prop 可以禁用按钮。

tsx
export const ButtonWithDisabled = () => {
  return <Button disabled>Button</Button>
}

禁用链接

当在链接上使用 disabled prop 时,你需要阻止链接的默认行为,并添加 data-disabled 属性。

Button
tsx
"use client"
export const ButtonWithDisabledLink = () => {
  return (
    <Button asChild>
      <a href="#" data-disabled="" onClick={(e) => e.preventDefault()}>
        Button
      </a>
    </Button>
  )
}

加载状态

Button 组件传入 loading loadingText props,可以显示一个加载 spinner 并添加加载文本。

tsx
export const ButtonWithLoading = () => {
  return (
    <Stack direction="row" gap="4" align="center">
      <Button loading>点击我</Button>
      <Button loading loadingText="保存中...">
        点击我
      </Button>
    </Stack>
  )
}

切换加载状态

下面是一个在切换按钮加载状态时保持按钮宽度不变的示例。

tsx
"use client"
export const ButtonWithLoadingToggle = () => {
  const [loading, setLoading] = useState(false)
  return (
    <VStack gap="4">
      <Button loading={loading} onClick={() => setLoading(!loading)}>
        点击我
      </Button>
      <Checkbox.Root
        size="sm"
        checked={loading}
        onCheckedChange={() => setLoading(!loading)}
      >
        <Checkbox.HiddenInput />
        <Checkbox.Control />
        <Checkbox.Label>Loading</Checkbox.Label>
      </Checkbox.Root>
    </VStack>
  )
}

import { Button, Checkbox, VStack } from "@chakra-ui/react"
import { useState } from "react"

Spinner 放置位置

使用 spinnerPlacement prop 可以更改 spinner 的位置。

tsx
export const ButtonWithSpinnerPlacement = () => {
  return (
    <ButtonGroup colorPalette="teal">
      <Button loading loadingText="加载中" spinnerPlacement="start">
        提交
      </Button>
      <Button loading loadingText="加载中" spinnerPlacement="end">
        继续
      </Button>
    </ButtonGroup>
  )
}

自定义 Spinner

使用 spinner prop 可以替换 spinner。

tsx
export const ButtonWithCustomSpinner = () => {
  return (
    <Button
      loading
      colorPalette="blue"
      spinner={<Spinner size="sm" color="white" />}
    >
      点击我
    </Button>
  )
}

import { Button, Spinner } from "@chakra-ui/react"

按钮组

使用 ButtonGroup 组件把按钮组合在一起。该组件允许你向内部按钮传递共同的 recipe 属性。

tsx
export const ButtonWithGroup = () => {
  return (
    <ButtonGroup size="sm" variant="outline">
      <Button colorPalette="blue">保存</Button>
      <Button>取消</Button>
    </ButtonGroup>
  )
}

吸附的按钮组

要让按钮之间无缝拼接,请传入 attached prop。

tsx
export const ButtonWithGroupFlushed = () => {
  return (
    <ButtonGroup size="sm" variant="outline" attached>
      <Button variant="outline">Button</Button>
      <IconButton variant="outline">
        <LuChevronDown />
      </IconButton>
    </ButtonGroup>
  )
}

import { Button, ButtonGroup, IconButton } from "@chakra-ui/react"
import { LuChevronDown } from "react-icons/lu"

拆分菜单

ButtonMenu 结合,并使用 Group 的无缝拼接模式创建一个带下拉菜单的拆分按钮。

tsx
const menuItems = [
  { label: "另存为草稿", value: "draft" },
  { label: "保存并发布", value: "publish" },
  { label: "保存并定时", value: "schedule" },
]

export const ButtonWithSplitMenu = () => {
  return (
    <Menu.Root positioning={{ placement: "bottom-end" }}>
      <Group attached>
        <Button variant="outline" size="sm">
          保存
        </Button>
        <Menu.Trigger asChild>
          <IconButton variant="outline" size="sm">
            <LuChevronDown />
          </IconButton>
        </Menu.Trigger>
      </Group>
      <Portal>
        <Menu.Positioner>
          <Menu.Content>
            {menuItems.map((item) => (
              <Menu.Item key={item.value} value={item.value}>
                {item.label}
              </Menu.Item>
            ))}
          </Menu.Content>
        </Menu.Positioner>
      </Portal>
    </Menu.Root>
  )
}

import { Button, Group, IconButton, Menu, Portal } from "@chakra-ui/react"
import { LuChevronDown } from "react-icons/lu"

响应式尺寸

size prop 上使用对象语法可以让按钮尺寸随断点变化。

tsx
export const ButtonWithResponsiveSize = () => {
  return (
    <Button rounded="3xl" size={{ base: "md", md: "lg" }}>
      Button
    </Button>
  )
}

圆角

使用 rounded prop 可以更改按钮的圆角半径。

语义化圆角

核心圆角

tsx
export const ButtonWithRadius = () => {
  return (
    <Stack gap="8">
      <Stack>
        <Text textStyle="sm">语义化圆角</Text>
        <ButtonGroup variant="subtle">
          <Button rounded="l1">圆角 l1</Button>
          <Button rounded="l2">圆角 l2</Button>
          <Button rounded="l3">圆角 l3</Button>
        </ButtonGroup>
      </Stack>

      <Stack>
        <Text textStyle="sm">核心圆角</Text>
        <ButtonGroup variant="subtle">
          <Button rounded="sm">圆角 sm</Button>
          <Button rounded="md">圆角 md</Button>
          <Button rounded="lg">圆角 lg</Button>
          <Button rounded="xl">圆角 xl</Button>
          <Button rounded="2xl">圆角 2xl</Button>
          <Button rounded="full">圆角 full</Button>
        </ButtonGroup>
      </Stack>
    </Stack>
  )
}

作为链接

使用 asChild prop 可以将按钮渲染成一个链接。

Button
tsx
export const ButtonAsLink = () => {
  return (
    <Button asChild>
      <a href="#">Button</a>
    </Button>
  )
}

引用(Ref)

以下示例展示了如何访问底层元素的引用。

tsx
const Demo = () => {
  const ref = useRef<HTMLButtonElement | null>(null)
  return <Button ref={ref}>点击我</Button>
}

自定义

自定义 recipe 之后,请运行 CLI 的 typegen 命令重新生成类型。查看 CLI 文档 了解如何在 postinstall、CI 和 monorepo 中运行 typegen。
bash
npx @chakra-ui/cli typegen

添加新的变体

使用 defineRecipe 函数给按钮添加一个新变体。在这个例子中,我们添加了一个支持 colorPalette prop 的 pill 变体。

tsx
// components/ui/provider.tsx
import { createSystem, defaultConfig, defineRecipe } from "@chakra-ui/react"

const buttonRecipe = defineRecipe({
  variants: {
    variant: {
      pill: {
        borderRadius: "full",
        px: "6",
        bg: "colorPalette.solid",
        color: "colorPalette.contrast",
        _hover: {
          bg: "colorPalette.solid/90",
        },
      },
    },
  },
})

const system = createSystem(defaultConfig, {
  theme: {
    recipes: { button: buttonRecipe },
  },
})

然后在你的按钮中使用 pill 变体:

tsx
<Button variant="pill" colorPalette="blue">
  胶囊按钮
</Button>

添加新的尺寸

使用 defineRecipe 函数给按钮添加一个新尺寸。

tsx
// components/ui/provider.tsx
import { createSystem, defaultConfig, defineRecipe } from "@chakra-ui/react"

const buttonRecipe = defineRecipe({
  variants: {
    size: {
      xxl: {
        h: "16",
        minW: "16",
        textStyle: "xl",
        px: "8",
      },
    },
  },
})

const system = createSystem(defaultConfig, {
  theme: {
    recipes: { button: buttonRecipe },
  },
})

然后在你的按钮中使用 xxl 尺寸:

tsx
<Button size="xxl">XXL 按钮</Button>

更改默认尺寸

使用 defaultVariants 属性可以更改按钮的默认尺寸。

tsx
// components/ui/provider.tsx
import { createSystem, defaultConfig, defineRecipe } from "@chakra-ui/react"

const buttonRecipe = defineRecipe({
  defaultVariants: {
    size: "lg",
  },
})

const system = createSystem(defaultConfig, {
  theme: {
    recipes: { button: buttonRecipe },
  },
})

更改默认变体

使用 defaultVariants 属性可以更改按钮的默认变体。

tsx
// components/ui/provider.tsx
import { createSystem, defaultConfig, defineRecipe } from "@chakra-ui/react"

const buttonRecipe = defineRecipe({
  defaultVariants: {
    variant: "outline",
  },
})

const system = createSystem(defaultConfig, {
  theme: {
    recipes: { button: buttonRecipe },
  },
})

属性(Props)

以下是 Button 组件的常用属性。

  • spinnerPlacement

    默认值:'start'

    'start' | 'end' | undefined

    spinner 的放置位置

  • colorPalette

    默认值:'gray'

    'gray' | 'red' | 'orange' | 'yellow' | 'green' | 'teal' | 'blue' | 'cyan' | 'purple' | 'pink'

    组件的颜色方案

  • size

    默认值:'md'

    '2xs' | 'xs' | 'sm' | 'md' | 'lg' | 'xl' | '2xl'

    组件的尺寸

  • variant

    默认值:'solid'

    'solid' | 'subtle' | 'surface' | 'outline' | 'ghost' | 'plain'

    组件的变体样式

  • loading

    默认值:false

    boolean | undefined

    为 true 时,按钮会显示一个加载 spinner。

  • loadingText

    默认值:

    React.ReactNode | undefined

    加载时显示的文本。

  • spinner

    默认值:

    React.ReactNode | undefined

    加载时显示的 spinner。

  • as

    默认值:

    React.ElementType

    要渲染的底层元素。

  • asChild

    默认值:false

    boolean

    将传入的子元素作为默认渲染的元素,并组合它们的 props 与行为。