ChatComposer 消息输入
带上下文托盘的 AI 消息输入框
<script>
import { ref } from 'vue'
const text = ref('')
const sent = ref<string[]>([])
function onSend(payload: { text: string }) {
sent.value.unshift(payload.text)
text.value = ''
}
</script>用法
基础
示例加载中...
托盘换位
tray 插槽在卡片外渲染托盘,trayPlacement 决定它在卡片下方(默认)或上方。
示例加载中...
搭配模式芯片
把 ModeChip 模式芯片 放进 toolbar-left 插槽。
示例加载中...
最佳实践
send只表示发送意图:请求成功后再清空modelValue,失败时保留文本供重试。- 请求进行中设置
submitting,防止重复发送。 attachments只作状态 chip;上传进度、删除与重试放在宿主或attachments插槽中。- 托盘内容保持一行且上下等高,换位时外框不变;托盘动作用 muted 色调的
TxModeChip。 - 托盘位置跟随语境切换(「连接应用」变为「选择项目」),不要循环换位作装饰。
API 参考
属性
| 属性 | 类型 | 默认值 | 说明 |
|---|---|---|---|
modelValue | string | '' | 输入框文本,配合 v-model 使用。 |
placeholder | string | 'Message…' | 占位文本。 |
ariaLabel | string | - | 输入框的可访问名称;缺省时用 placeholder。 |
disabled | boolean | false | 禁用输入、发送与附件操作。 |
submitting | boolean | false | 请求进行中,阻止发送。 |
allowAttachmentWhileSubmitting | boolean | false | submitting 期间仍允许附件操作。 |
minRows | number | 3 | 静止高度(行),随内容增高。 |
maxRows | number | 6 | 增高上限(行),超出后滚动;不低于 minRows。 |
sendOnEnter | boolean | true | 启用键盘发送。 |
sendOnMetaEnter | boolean | true | 键盘发送需按 Meta/Ctrl+Enter。 |
allowEmptySend | boolean | false | 文本为空但有附件时允许发送。 |
sendButtonText | string | 'Send' | 发送图标按钮的可访问名称。 |
showAttachmentButton | boolean | false | 显示默认的 + 附件按钮。 |
attachmentButtonText | string | 'Attach' | + 附件按钮的可访问名称。 |
attachments | ChatComposerAttachment[] | [] | 输入框上方的附件 chip。 |
trayPlacement | 'top' | 'bottom' | 'bottom' | 托盘在卡片上方或下方;改变时播放换位动效。 |
trayLabel | string | - | 设置后托盘渲染为带此名称的 role="group"。 |
事件
| 事件 | 参数 | 说明 |
|---|---|---|
update:modelValue | string | 输入时触发。 |
send | { text: string } | 允许发送时触发,文本已 trim。 |
attachmentClick | - | 允许附件操作时,点击附件按钮触发。 |
paste | ClipboardEvent | 透传输入框的 paste。 |
attachmentAdd | File[] | 粘贴或拖入文件时触发;上传由宿主负责。 |
focus | FocusEvent | 透传输入框的 focus。 |
blur | FocusEvent | 透传输入框的 blur。 |
插槽
| 插槽 | 作用域 | 说明 |
|---|---|---|
tray | - | 卡片外的托盘内容。 |
attachments | { attachments } | 替换默认附件 chip。 |
toolbar | { send, disabled, attachmentClick } | 替换默认操作行。 |
toolbar-left | { disabled } | 追加到默认操作行左侧。 |
actions | { send, disabled } | 追加到发送按钮之前。 |
footer | - | 卡片内、操作行下方的内容。 |
类型
interface ChatComposerAttachment {
id: string // chip 的 key
label: string // chip 文本,超宽时省略
kind?: string // 文本后的类型标记,以大写显示
pending?: boolean // 处理中,chip 改为琥珀色
}
CSS 变量
| 变量 | 默认值 | 说明 |
|---|---|---|
--tx-chat-composer-radius | 18px | 外壳与卡片共用的圆角。 |
概述
- 文本 trim 后非空才能发送;
allowEmptySend为真且有附件时可只发附件。disabled、submitting都阻止发送。 - 附件操作(按钮、粘贴、拖入文件)在
disabled时被阻止;submitting时也被阻止,除非设置allowAttachmentWhileSubmitting。 sendOnMetaEnter为真时 Meta/Ctrl+Enter 发送;为假时 Enter 发送,Shift+Enter 换行。- 输入框从
minRows行随内容增高,到maxRows行后滚动(field-sizing: content);不支持的浏览器固定为minRows行。 - 根元素是外壳,透传的 class 与属性落在外壳上,输入卡片是
.tx-chat-composer__card;增删托盘不重建 textarea,焦点与输入法状态保留。 - 托盘只在提供
tray插槽时渲染。焦点在离开的托盘中时,换位后移到输入框;减少动态效果或无 Web Animations API 时直接落到终态。
技术实现
- 换位时旧托盘由 CSS 过渡淡出;卡片滑动与外壳高度是 Web Animations 驱动的 FLIP,延迟 70ms、时长 450ms、曲线
cubic-bezier(0.65, 0.16, 0.1, 0.88)。 - 动效参考:@flohoeller 的 Chatbox 组件视频。
- 源码:
packages/tuffex/packages/components/src/chat/src/TxChatComposer.vue。
查看源码
packages/tuffex/packages/components/src/chat-composer/index.ts