# Button

按钮组件，用于触发操作或导航。支持多种类型、颜色、尺寸，以及 loading 状态和异步操作。

## 适用场景

- 触发表单提交、确认操作
- 页面内的操作入口（新建、编辑、删除等）
- 需要 loading 反馈的异步操作按钮
- 作为链接按钮（href 模式）

## Props

| 名称 | 类型 | 默认值 | 必填 | 说明 |
|------|------|--------|------|------|
| className | `string` | `""` | 否 | 自定义 class |
| size | `"md" \| "sm" \| "xs" \| "lg" \| "xl"` | `-` | 否 | 尺寸，默认使用 config context `baseSize` |
| disabled | `boolean` | `false` | 否 | 是否禁用 |
| type | `"normal" \| "intensive" \| "important" \| "ghost" \| "plain"` | `"normal"` | 否 | 类型 |
| color | `"normal" \| "brand" \| "success" \| "danger" \| "warning"` | `"normal"` | 否 | 颜色。已废弃的 `"primary"` 仍会在运行时归一到 `"brand"`，但不再作为合法类型 |
| icon | `FC<{}>` | `-` | 否 | 图标组件 |
| loading | `boolean` | `-` | 否 | 控制 loading 状态。loading 时 click 无效但无 disabled 样式 |
| loadingIcon | `SvgFC` | `-` | 否 | 自定义 loading 图标 |
| loadingType | `"normal" \| "icon-only"` | `-` | 否 | loading 时是否保留按钮文字 |
| loadingDelay | `number` | `-` | 否 | loading 图标延迟显示时间（ms），0 为立即显示 |
| href | `string` | `-` | 否 | 设置后渲染为 `<a>` 元素 |
| target | `string` | `-` | 否 | `<a>` 的 target 属性 |
| download | `string` | `-` | 否 | `<a>` 的 download 属性，指示浏览器下载资源而非导航 |
| onClick | `(e: MouseEvent) => void \| Promise<unknown>` | `-` | 否 | 点击回调。返回 Promise 时自动进入 async loading 模式并防连击 |
| refHTMLElement | `Ref<HTMLButtonElement> \| Ref<HTMLAnchorElement>` | `-` | 否 | 获取底层 DOM 元素 |

## 典型用法

### 按钮类型

```tsx
import {Button, SvgEdit} from '@befe/brick'

<Button>普通</Button>
<Button icon={SvgEdit}>普通带图标</Button>
<Button type={'intensive'}>加强</Button>
<Button type={'important'}>重要</Button>
<Button type={'plain'}>纯文字</Button>
<Button type={'ghost'}>幽灵</Button>

// 禁用状态
<Button disabled>普通</Button>
<Button disabled type={'intensive'}>加强</Button>
```

### 尺寸

```tsx
<Button size={'xs'}>超小号</Button>
<Button size={'sm'}>小号</Button>
<Button size={'md'}>中号</Button>
<Button size={'lg'}>大号</Button>
<Button size={'xl'}>特大号</Button>
```

### 颜色

```tsx
<Button color={'brand'} type={'intensive'} icon={SvgEdit}>加强</Button>
<Button color={'brand'} type={'important'} icon={SvgEdit}>重要</Button>
<Button color={'success'} type={'intensive'} icon={SvgEdit}>成功</Button>
<Button color={'danger'} type={'important'} icon={SvgEdit}>危险</Button>
<Button color={'warning'} type={'plain'} icon={SvgEdit}>警告</Button>
```

### Loading 状态

> `loading` 本身具备禁用 onClick 的特性；`loading + disabled` 则完全无交互反应

```tsx
import {useState} from 'react'
import {Button, SvgEdit} from '@befe/brick'

// 受控 loading，保留文字
<Button loading={isLoading}>提交</Button>
<Button loading={isLoading} icon={SvgEdit} type={'important'}>反白</Button>

// loading 时只显示图标（无文字）
<Button loading={isLoading} loadingType={'icon-only'}>提交</Button>
```

### 异步操作（自动 loading + 防连击）

> onClick 返回 Promise 时自动触发 async loading 状态，直到 Promise resolve

```tsx
import {Button} from '@befe/brick'

const runAsync = () => {
    return new Promise(resolve => {
        setTimeout(() => resolve('ok'), 5000)
    })
}

<Button type={'important'} onClick={runAsync}>run async</Button>
```

### 按钮间距

> 分组按钮用 `GroupedButtons` 容器控制间距：容器内相邻 `Button` 用组内间距，相邻的两个 `GroupedButtons` 之间用组间间距。等价于手写 `.brick-grouped-buttons`，推荐用组件写法。

```tsx
import {Button, GroupedButtons} from '@befe/brick'

<GroupedButtons>
    <Button>分组一</Button>
    <Button>分组一</Button>
</GroupedButtons>
<GroupedButtons>
    <Button>分组二</Button>
    <Button>分组二</Button>
    <Button>分组二</Button>
</GroupedButtons>
```

## 注意事项

- `color="primary"` 已不再是合法类型，运行时仍会归一到 `color="brand"` 并告警，请直接改用 `color="brand"`
- `type="plain"` 的纯图标（icon-only）按钮：不显式给 `color` 时沿用原始 icon 中性色板；显式给 `color`（含 `"normal"`）则跟随对应 plain 文字色板（含各状态）
- `loading` 状态自带防连击（click 无效），但样式上不同于 `disabled`
- `onClick` 返回 `Promise` 时自动进入 async loading，无需手动管理 loading 状态，且自动防连击
- `loadingDelay` 可避免快速操作时 loading 图标的视觉闪烁
- 语义区分：需要 `onClick` 处理的用 Button，只需 `href` 的用 Link 组件
- 不支持 `props.style`

## GroupedButtons

分组按钮容器。承载 `.brick-grouped-buttons` 布局：容器内相邻 `Button` 使用组内间距，相邻的两个 `GroupedButtons` 之间使用组间间距。仅固化布局，不改变视觉。

### Props

| 名称 | 类型 | 默认值 | 必填 | 说明 |
|------|------|--------|------|------|
| className | `string` | `-` | 否 | 自定义 class |

> 除上表外，其余属性透传到根 `<div>`（继承 `HTMLAttributes<HTMLDivElement>`）。

### 注意事项

- 组件渲染出的 class 与手写 `<div className="brick-grouped-buttons">` 完全一致，存量手写用法无需迁移即可继续工作
- 组间间距靠相邻的两个 `GroupedButtons` 触发，无需额外包裹层
