# 发送按钮

## 使用方法

`ChatSendButton` 就是输入区里那颗要「发送」还是「停止」的按钮。放在 `ChatComposer` 里面时，它自己从上下文里知道现在能不能发、是不是在流式输出、该回调谁；单独用的话，这些状态要你自己传。

```ts
import { ChatSendButton } from '@astryx-vue/core/Chat'
```

### 结构

- **操作按钮**: 圆形的纯图标 Button，暴露本地化的「发送」或「停止」名字，同时是 chat-send-button 主题的挂载点。

## 建议

| 指引 | 实践 |
| --- | --- |
| 推荐 | 希望发送和停止的行为跟着输入区走，就把它放进 `ChatComposer`。 |
| 推荐 | 单独用时，把状态和对应的 `send` 或 `stop` 监听都显式给全。 |
| 推荐 | 换成自己的图标时，别把本地化的「发送」「停止」无障碍名字弄丢。图标只是装饰，不能成为唯一的名字来源。 |
| 避免 | 停止状态下没有可用的停止处理函数，属性里也没给、上下文里也没有。 |
| 避免 | 以为 `isDisabled` 会禁用停止。它只管发送那一边。 |

## 示例

常见的用法、变化和状态。

### ChatSendButton — 自定义图标

用 sendIcon 和 stopIcon 插槽换成自己的图标。想让对话有点性格就用它：发消息用纸飞机，AI 生成用闪闪，确认流程用对勾。

```vue
<script setup lang="ts">
import { ChatSendButton } from '@astryx-vue/core/Chat'
import { Icon } from '@astryx-vue/core/Icon'
import { HStack, VStack } from '@astryx-vue/core/Stack'
import { Text } from '@astryx-vue/core/Text'
</script>

<template>
  <VStack :gap="4">
    <Text type="supporting" color="secondary">
      Custom icons for send and stop states
    </Text>
    <HStack align="center" :gap="4">
      <ChatSendButton :is-disabled="false">
        <template #sendIcon>
          <Icon name="heroicons:paper-airplane-solid" />
        </template>
      </ChatSendButton>
      <ChatSendButton :is-disabled="false">
        <template #sendIcon>
          <Icon name="heroicons:check-solid" />
        </template>
      </ChatSendButton>
      <ChatSendButton :is-disabled="false">
        <template #sendIcon>
          <Icon name="heroicons:sparkles-solid" />
        </template>
      </ChatSendButton>
      <ChatSendButton is-stop-shown>
        <template #stopIcon>
          <Icon name="heroicons:x-circle" />
        </template>
      </ChatSendButton>
    </HStack>
  </VStack>
</template>
```

### ChatSendButton — 在输入区里

放在输入区里的发送按钮，状态全从上下文自己读。不用接线，输入框有内容它就亮起来。

```vue
<script setup lang="ts">
import { ChatComposer } from '@astryx-vue/core/Chat'
import { ref } from 'vue'

const value = ref('Hello, how can you help?')
</script>

<template>
  <ChatComposer v-model="value" />
</template>
```

### ChatSendButton — 各种状态

不能发、可以发、正在流式输出三种状态。按钮会根据流式状态自动在主色的发送和次色的停止之间切换。

```vue
<script setup lang="ts">
import { ChatSendButton } from '@astryx-vue/core/Chat'
import { HStack, VStack } from '@astryx-vue/core/Stack'
import { Text } from '@astryx-vue/core/Text'
</script>

<template>
  <VStack :gap="2">
    <Text type="supporting" color="secondary">
      Disabled → Ready → Streaming
    </Text>
    <HStack align="center" :gap="3">
      <ChatSendButton is-disabled />
      <ChatSendButton :is-disabled="false" />
      <ChatSendButton is-stop-shown />
    </HStack>
  </VStack>
</template>
```

## 属性

| 属性 | 类型 | 默认值 | 说明 |
| --- | --- | --- | --- |
| `isStopShown` | `boolean` | 跟随外层输入区 | 显示停止而不是发送。放在输入区里不传，就让外层决定。 |
| `isDisabled` | `boolean` | 取决于草稿能不能发 | 禁用发送，不禁用停止。放在输入区里不传，就跟着外层能不能发走。 |
| `size` | `'sm' \| 'md'` | `'md'` | 按钮尺寸，直接交给 `Button`。 |

## 事件

| 事件 | 参数 | 说明 |
| --- | --- | --- |
| `send` | — | 按了发送。在输入区里没监听这个事件时，它会把当前草稿提交掉。 |
| `stop` | — | 按了停止。在输入区里没监听这个事件时，会走外层的停止逻辑。 |
| `click` | `MouseEvent` | 发送或停止之后跟着触发。 |

## 插槽

| 插槽 | 说明 |
| --- | --- |
| `sendIcon` | 换掉那个向上的箭头。 |
| `stopIcon` | 换掉那个停止方块。 |
