# 按钮 · Button

- 页面: https://jiguang132.com/zh/resources/astryx/docs/button
- 资源: Astryx (https://jiguang132.com/zh/resources/astryx.md)
- 全部指南: https://jiguang132.com/zh/resources/astryx/docs.md

触发保存、提交或确认等操作；可选择不同强调程度、尺寸及加载状态。

## 安装与前置条件

```bash
npm install @astryxdesign/core@0.7.1 @astryxdesign/theme-neutral@0.7.1 @stylexjs/stylex@0.19.0
```

需要 React 19+，按顺序导入基础 CSS 和主题，并设置 Theme Provider。参见[开始使用](/resources/astryx/docs/getting-started)。

## 示例与使用方式

- **按钮 · 综合展示 1**：首先体验这个示例，再查看代码理解组件的组合方式。
- **按钮 · 浮动 2**：可交互查看这一用法的行为，复制代码时保留它实际使用的属性与导入。
- **按钮 · 尺寸变化 / 样式变化 / 样式 3**：可交互查看这一用法的行为，复制代码时保留它实际使用的属性与导入。
- **按钮 · 样式变化 / 样式 4**：可交互查看这一用法的行为，复制代码时保留它实际使用的属性与导入。
- **按钮 · 交互示例 5**：可交互查看这一用法的行为，复制代码时保留它实际使用的属性与导入。
- **按钮 · 包含图标 6**：可交互查看这一用法的行为，复制代码时保留它实际使用的属性与导入。

## API 与上游详细参考

优先使用 0.7.1 官方中文说明；上游尚未提供中文的条目保留英文。属性名、类型及默认值保持原生 API，不把示例状态名称当成组件属性。

## Button

Button triggers an action when clicked. Use it for form submissions, confirmations, navigation, or any interaction that needs a clear call to action.

| 属性 | 类型 | 默认值 | 说明 |
|---|---|---|---|
| label * | string |  | 无障碍标签；纯图标按钮时用作 aria-label。 |
| variant | 'primary' \| 'secondary' \| 'ghost' \| 'destructive' | 'secondary' | 视觉样式变体。 |
| size | 'sm' \| 'md' \| 'lg' | 'md' | 尺寸变体。 |
| elevation | 'none' \| 'low' \| 'med' \| 'high' | 'none' | 浮动按钮（如 FAB）的静止阴影深度。`none` 为默认扁平按钮；在 ButtonGroup 内忽略。 |
| type | 'button' \| 'submit' \| 'reset' | 'button' | HTML 按钮类型属性。 |
| name | string |  | 表单提交的 HTML name 属性。 |
| value | string \| number \| readonly string[] |  | 表单提交的 HTML value 属性。 |
| form | string |  | 通过 ID 将按钮与表单元素关联。 |
| isLoading | boolean | false | 显示加载旋转器并禁用交互。通过实时区域播报"Loading"。 |
| isInterruptible | boolean | false | Keep the button clickable while a clickAction is pending: the spinner and aria-busy still show, but the button is not disabled and the action is not deduped, so a re-click lands and interrupts the in-flight action with a fresh one. |
| isDisabled | boolean | false | 禁用按钮。存在工具提示时，使用 aria-disabled 代替原生 disabled 以保持可聚焦。 |
| icon | ReactNode |  | 图标元素。未显式指定尺寸的 Astryx Icon 在 sm/md 按钮中默认为 sm，在 lg 按钮中默认为 md。仅提供 icon 而不提供 children 时，按钮渲染为正方形的纯图标按钮。 |
| isIconOnly | boolean | false | When true, renders as a square icon-only button with label as aria-label. Requires icon. Tip: for a dedicated icon-only button component, use IconButton from '@astryxdesign/core/IconButton' instead. |
| width | SizeValue |  | 按钮宽度。数字按像素处理，字符串按原样使用（如 '100%' 表示全宽按钮）。默认按内容自适应宽度，不会超出容器；行宽不足时标签以省略号截断；纯图标按钮保持正方形。 |
| children | ReactNode |  | 可选的可见内容覆盖；label 仍然是必需的（用于无障碍名称）。大多数情况使用 <Button label="Save" />。 |
| endContent | ReactElement<IconProps> \| ReactElement<BadgeProps> |  | 标签后方渲染的尾部图标或徽章。仅接受 <Icon> 或 <Badge>。纯图标按钮时忽略。颜色继承自按钮变体。 |
| tooltip | string |  | 悬停时显示的提示文本。 |
| onClick | (e: MouseEvent) => void |  | 标准点击处理函数（从 ButtonHTMLAttributes 透传）。 |
| clickAction | (e: MouseEvent) => void \| Promise<void> |  | 异步点击处理函数。返回的 Promise 处于 pending 状态时显示加载状态。 |
| href | string |  | When provided, renders the button as a link element (<a> or custom link component). The destination follows the shared navigation rule described on the Link `href` prop. |
| as | ComponentType |  | Custom link component to use when href is provided (e.g. Next.js Link). |
| target | string |  | HTML target attribute when rendered as a link (e.g. "_blank"). |
| rel | string |  | HTML rel attribute when rendered as a link (e.g. "noopener noreferrer"). |

### 使用建议

- Reserve primary for the single most important action in the view. Use secondary or ghost for everything else based on emphasis.
- Write labels that describe the action ("Save changes", "Delete account", "Send invite"), not vague labels like "OK" or "Click here".
- Show a loading state for actions that take time, like saving or submitting, so the user knows it is working.
- Always provide a label for icon-only buttons so screen readers can announce what the button does. Add a tooltip for sighted users.
- 避免：Place more than one primary button in the same view; this dilutes the visual hierarchy.
- 避免：Use the destructive variant without a confirmation step for irreversible actions like deleting data.
- 避免：Use a button for navigation. If it only takes the user to another page, use a link instead. Buttons are for actions like saving, deleting, or submitting.

### Actions in narrow rows

```tsx
import {useState} from 'react';
import {Button} from '@astryxdesign/core/Button';
import {Card} from '@astryxdesign/core/Card';
import {Heading} from '@astryxdesign/core/Heading';
import {HStack} from '@astryxdesign/core/HStack';
import {Icon} from '@astryxdesign/core/Icon';
import {IconButton} from '@astryxdesign/core/IconButton';
import {StackItem} from '@astryxdesign/core/Stack';
import {TextInput} from '@astryxdesign/core/TextInput';
import {VStack} from '@astryxdesign/core/VStack';

// On a phone (or any card narrower than its actions), a labelled Button
// shrinks with its row and truncates its label with an ellipsis instead of
// overflowing or being clipped by the card. The full label stays the
// accessible name. Icon-only buttons keep their square size.
function ReviewersCard() {
  const [emails, setEmails] = useState('');
  return (
    <Card maxWidth={560}>
      <VStack gap={4}>
        <HStack gap={2} vAlign="center">
          <StackItem size="fill">
            <Heading level={3} maxLines={1}>
              Design review
            </Heading>
          </StackItem>
          <Button label="Request review from the design team" size="sm" />
          <IconButton
            label="More review options"
            icon={<Icon icon="moreHorizontal" />}
            variant="ghost"
            size="sm"
          />
        </HStack>
        <TextInput
          label="Reviewer emails"
          placeholder="name@example.com"
          value={emails}
          onChange={setEmails}
        />
        {/* In a 320px form footer the long primary action truncates.
            StackItem size="static" keeps the short Cancel label whole. */}
        <HStack gap={2} hAlign="end">
          <StackItem size="static">
            <Button label="Cancel" variant="secondary" />
          </StackItem>
          <Button label="Send invitations to all 12 reviewers" variant="primary" />
        </HStack>
      </VStack>
    </Card>
  );
}
```

### 主题 API

```json
{
  "targets": [
    {
      "className": "astryx-button",
      "visualProps": [
        "size",
        "variant",
        "elevation"
      ]
    }
  ],
  "vars": [
    {
      "name": "--_button-radius",
      "description": "圆角半径",
      "default": "var(--radius-element)",
      "private": true
    },
    {
      "name": "--button-focus-offset",
      "description": "焦点环轮廓偏移",
      "default": "var(--focus-outline-offset)"
    },
    {
      "name": "--button-icon-only-aspect",
      "description": "纯图标按钮的宽高比",
      "default": "1 / 1"
    }
  ],
  "derived": [
    {
      "property": "borderRadius",
      "vars": [
        "--_button-radius"
      ]
    }
  ]
}
```

### 无障碍

- **Text label**: Button text must have at least 4.5:1 contrast with the button background in every state. For Hover and Pointer down, measure the final background after the overlay is applied. — 4.5:1
- **Essential icon or spinner arc**: An icon used instead of text must have at least 3:1 contrast with the button background. The moving spinner arc must also meet 3:1. An icon beside a visible label does not need its own check. — 3:1
- **Badge text**: Badge text inside a button must have at least 4.5:1 contrast with the Badge background. Check all 14 built-in Badge colors in Rest, Hover, and Pointer down on page and surface backgrounds. This covers 336 pairs per mode. Check custom end content separately. — 4.5:1
- **Visible control boundary**: The button edge needs 3:1 contrast only when users need it to see the control. A text-only button can rely on its label. — 3:1 if needed
- **Keyboard focus indicator**: The focus outline needs at least 3:1 contrast with the area around the button. Check every style. Destructive buttons use a red outline. — 3:1
- **Disabled appearance**: Disabled controls do not need to meet these contrast ratios. — Not required

### 组件结构

- **Icon**: A leading icon that reinforces the label, like a trash icon on a Delete button.
- **Label**: The visible text describing the action. Also used as the accessible name.
- **End content**: A trailing badge or icon after the label, like a notification count or dropdown arrow.
- **Spinner**: Replaces the icon during loading to show the action is in progress.


## 完整示例的额外依赖

部分示例使用独立图标包。示例清单中的每条安装命令包含该示例实际需要的依赖；若要运行本页全部示例，还需安装：

```bash
npm install @heroicons/react@2.2.0
```

---

JGuang 全部资源索引: https://jiguang132.com/llms.txt
