对话
ChatLayout
| 名称 | 类型 | 默认值 | 说明 |
|---|---|---|---|
density | 'compact' | 'balanced' | 'spacious' | 'balanced' | 间距、气泡宽度和底部磨砂。单条消息可以自己覆盖。 |
scrollRef | HTMLElement | null | - | 代替布局自己滚动的元素。不传时由布局滚动。自己滚动时底部停靠是 sticky,外部滚动时改成 fixed。 |
showScrollButton | boolean | true | 是否渲染内置的回到底部按钮。用 scrollButton 插槽替换,或者根本不需要这个按钮时设为 false。 |
| 名称 | 说明 |
|---|---|
default | 会话记录,通常放一个 ChatMessageList。 |
composer | 贴在底部,位于磨砂层之上。 |
empty | 没有默认插槽时显示。 |
scrollButton | 替换内置按钮。参数:isVisible、label(只在有未读新消息时有值)、scrollToBottom。 |
模板引用暴露 element 和 scrollToBottom()。scrollToBottom 会清掉「有新消息」,再用弹簧滚到底部。
ChatLayoutScrollButton
| 名称 | 类型 | 默认值 | 说明 |
|---|---|---|---|
isVisible | boolean | - | 胶囊是否可见。隐藏时仍挂在树上,方便淡出,并带 inert。 |
label | string | - | 把胶囊拉宽。不传时只有向下的图标。无障碍名称回退到「滚动到底部」。 |
按下按钮时发出 click。
ChatMessageList
| 名称 | 类型 | 默认值 | 说明 |
|---|---|---|---|
align | 'top' | 'bottom' | 'bottom' | 消息不到一屏时贴顶还是贴底。'bottom' 在消息前面留一块弹性空白;'top' 不留,消息从顶上排。 |
density | 'compact' | 'balanced' | 'spacious' | 'balanced' | 传给没有自己设置密度的消息。 |
gap | SpacingStep | - | 顶层行之间的间距,走间距刻度。只改间距,不改内边距。 |
scrollToTopAction | () => Promise<void> | - | 顶部哨兵进入滚动容器时加载更早的消息。Promise 结束前显示加载指示。上一次还没结束时,再次进入不会重复触发。 |
isStreaming | boolean | false | 助手消息还在增长时设置 aria-busy。 |
label | string | 本地化的「消息列表」 | 日志的无障碍名称。 |
default 插槽是各行。emptyState 在没有 default 时显示,empty 是它的别名。根节点是 role="log",aria-live="polite"。
ChatMessage
| 名称 | 类型 | 默认值 | 说明 |
|---|---|---|---|
sender | 'user' | 'assistant' | 'system' | - | 这条消息是谁发的。system 居中,头像、名字和元信息都忽略。 |
name | string | - | 纯文本名字。正文以气泡开头时,更适合把名字放在气泡上。 |
density | 'compact' | 'balanced' | 'spacious' | 先看列表,再回退到 'balanced' | 只作用于这一行的密度。 |
插槽:default(正文)、avatar、name(替换属性)、metadata。article 的名称优先用可见名字,否则是「来自{发送者}的消息」。
ChatMessageBubble
| 名称 | 类型 | 默认值 | 说明 |
|---|---|---|---|
variant | 'filled' | 'ghost' | 'filled' | filled 有发送者底色。ghost 去掉背景和上下内边距,混排内容仍然对齐。 |
name | string | - | 与气泡内边距对齐的名字。 |
group | 'first' | 'middle' | 'last' | - | 多条气泡叠在一起时收紧一角。单独一条不用传。 |
发送者和密度来自外层 ChatMessage。插槽:default、name、metadata。属性落到气泡元素上。
ChatMessageMetadata
| 名称 | 类型 | 默认值 | 说明 |
|---|---|---|---|
timestamp | string | - | 时间等短文本。timestamp 插槽会替换它。 |
footer | string | - | 次要文字,例如模型名。footer 插槽会替换它。 |
status | 'sending' | 'sent' | 'delivered' | 'read' | 'error' | - | 投递状态。时间、补充文字和状态都没有时,这一行不渲染。 |
状态图标的无障碍名称会本地化,例如「消息已读」。用户消息上,各项从行尾开始排。
ChatSystemMessage
| 名称 | 类型 | 默认值 | 说明 |
|---|---|---|---|
variant | 'default' | 'divider' | 'default' | default 是居中的一行。divider 两侧各有一条线。根节点是 role="status"。 |
插槽:default,以及 icon(divider 时忽略)。
ChatToolCalls
| 名称 | 类型 | 默认值 | 说明 |
|---|---|---|---|
calls | ChatToolCallItem[] | - | 一轮回复里的工具调用。空数组不渲染。每项可以带 name、status、target、duration、node、additions、deletions、stats、errorMessage、key、resultDetail、data。detail 是 resultDetail 的别名。 |
label | string | 本地化的「{count} 个工具调用」 | 分组展开时的标题。 |
v-model:isExpanded | boolean | - | 多条调用这一组的受控展开状态。 |
defaultIsExpanded | boolean | false | isExpanded 未绑定时的初始状态。 |
发出 expandedChange,参数是下一个布尔值。detail 插槽收到 { call },用来替换 call.resultDetail。分组收起时只显示最新一条;面板在打开前是 inert。等待中和进行中用加载指示。错误会放进一段视觉隐藏的文字里读出来。
ChatReasoning
| 名称 | 类型 | 默认值 | 说明 |
|---|---|---|---|
label | string | 本地化的「思考中」 | 标题。 |
duration | string | - | 流式结束后跟在标题后面,例如 12s。 |
isStreaming | boolean | false | 标题闪动,并藏起预览和耗时。 |
v-model:isExpanded | boolean | - | 受控展开状态。 |
defaultIsExpanded | boolean | false | isExpanded 未绑定时的初始状态。 |
默认插槽是完整推理。只有一个文本节点时,它也是收起状态的预览。发出 expandedChange。收起时面板是 inert。
ChatTypingIndicator
| 名称 | 类型 | 默认值 | 说明 |
|---|---|---|---|
names | string[] | - | 正在输入的人。空字符串会被丢掉。不传名字时只有三个点。一个人、两个人、三个及以上各有一句文案。 |
根节点是 role="status",并带 aria-live="polite"。文案就写在这个区域里,不再经 useAnnounce 播第二遍。
ChatUnreadDivider
| 名称 | 类型 | 默认值 | 说明 |
|---|---|---|---|
label | string | 本地化的「新消息」 | 线末端的短标签。无障碍名称是「{label}以下是未读消息」。 |
根节点是 role="separator"。它没有 .astryx-chat-message,新消息追踪不会把它当成一条消息。
ChatComposer
| 名称 | 类型 | 默认值 | 说明 |
|---|---|---|---|
modelValue | string | - | 受控草稿,用 v-model 绑定。不传时由外壳自己保存。 |
placeholder | string | 当前语言的「输入消息……」 | 草稿为空时的占位文字。 |
isDisabled | boolean | false | 停用编辑和发送。正在生成时如果显示停止,停止按钮仍然可以点。 |
density | 'compact' | 'balanced' | 'spacious' | 'balanced' | 外壳内边距。宽松和均衡用同一套间距。 |
elevation | 'low' | 'none' | 'low' | 低阴影在悬停和焦点时加深。none 是平的,靠边框区分。只有键盘把焦点放进编辑器时才画出焦点环。 |
isStopShown | boolean | false | 用停止代替发送。 |
status | { type: 'error' | 'warning', message?: string } | - | 错误用 alert,警告用 status。 |
statusPosition | 'top' | 'bottom' | 'bottom' | 状态条贴在外壳上方或下方,并伸进圆角后面。 |
| 名称 | 参数 | 说明 |
|---|---|---|
submit | value: string | 草稿去掉首尾空白后仍有内容时发出,然后清空草稿。 |
stop | - | 停止被点下。 |
change | value: string | 草稿变化,包括发送后的清空。 |
update:modelValue | value: string | 和 change 一起发出,给 v-model 用。 |
插槽有 drawer、headerActions、headerContext、input、footerActions、sendActions、sendButton。模板引用暴露 element。
ChatComposerInput
| 名称 | 类型 | 默认值 | 说明 |
|---|---|---|---|
modelValue | string | - | 单独受控时使用。放在外壳里且不传时,跟外壳的草稿走。 |
placeholder | string | 外壳或当前语言的占位 | 空编辑器上的提示。 |
maxRows | number | 8 | 超过这么多行后开始内部滚动。一行按 22px 算。 |
triggers | ChatComposerTrigger[] | - | 在词首输入触发字符时打开建议列表。触发器上的 hasMultiWordQuery 让查询穿过空格和标点,直到换行、超过 64 个字符,或同一个触发字符再次出现。不设时,空格或制表符结束查询。多词查询没有匹配、也没写 emptySearchText 时,列表先藏起来。有触发器时编辑器是 combobox。 |
debounceMs | number | 150 | 异步搜索的等待。同步结果不延迟,第一次异步搜索立刻开始。 |
hasHistory | boolean | true | 光标在开头时上方向键取回上一条已发送草稿,在末尾时下方向键往回走。 |
label | string | 当前语言的「消息输入框」 | 编辑器的无障碍名称。 |
isDisabled | boolean | 外壳的停用状态 | 停用编辑。 |
pasteAsToken | useChatPasteAsToken 的返回值 | false | 超过 200 字变成标记 | 传 false 时长文本按原文插入。 |
pasteAction | (event, text) => boolean | void | - | 纯文本粘贴的第一站。返回 true 时输入框不再自己插入。 |
事件有 change、update:modelValue、submit、files、keydown。files 来自粘贴或拖入的文件,拖入不会让浏览器打开文件。keydown 在建议列表处理完之后发出,preventDefault 会跳过回车发送和历史。模板引用上有 insertToken、expandToken、insertText、focus、getValue。
ChatComposerDrawer
| 名称 | 类型 | 默认值 | 说明 |
|---|---|---|---|
count | number | - | 传入后才能折叠,并显示在默认摘要里。 |
label | string | 当前语言的「项目」 | 摘要和展开、折叠的无障碍名称都用它。 |
isCollapsed | boolean | - | 受控折叠,用 v-model:is-collapsed。 |
defaultIsCollapsed | boolean | false | 未绑定时的初始状态。 |
collapsedChange 在折叠状态变化时发出。默认插槽是展开后的内容。collapsedSummary 替换计数和名称,按钮自己仍带无障碍名称。
ChatSendButton
| 名称 | 类型 | 默认值 | 说明 |
|---|---|---|---|
isStopShown | boolean | 外壳的停止状态 | 停止用次要按钮,发送用主要按钮。停止不受停用影响。 |
isDisabled | boolean | 草稿为空或外壳停用 | 只停用发送。 |
size | 'sm' | 'md' | 'md' | 按钮尺寸。外壳会把圆角收成和外边框同心的圆形。 |
send、stop、click 三个事件。sendIcon 和 stopIcon 替换上箭头和方块。放在外壳里且没有自己监听时,点击会提交当前草稿或发出外壳的停止。
ChatDictationButton
需要传入 useChatDictation 或 useSpeechRecognition 的返回值。size 默认 md。isHiddenWhenUnsupported 默认 true,不支持时不渲染;设为 false 时按钮留着并停用。label 覆盖开始或停止听写的无障碍名称。听的时候按钮上是五根音量条,音量过大时颜色从强调色混向错误色。
ChatTokenizedText
默认插槽放消息文字;要直接传字符串时用 text 属性,效果一样。tokens 里每个非空 value 按字面替换成徽章或自定义内容。空 value 会被忽略。同一组对象可以同时给输入框的 onSelect 和这里用。
ChatComposerTokenElement
包住一枚标记,让它在可编辑区域里不可编辑,并带上序列化用的值。一般由输入框自己插入,需要在气泡外单独画一枚时也可以直接用。
组合式函数
useChatStreamScroll({ scrollRef }) 跟着 scrollRef 的底部走。内容第一次能滚时直接跳到底;之后的增长用弹簧,除非用户要求减少动效。向上滚会立刻松开。停在距底部 10px 以内会重新贴住。isScrolledUp 决定按钮出不出现。
useChatNewMessages({ isLocked, onResize }) 看着记录高度。未贴底时,最后一个 .astryx-chat-message 换了,hasNewMessages 变成 true,直到 dismiss()。ChatLayout 会播报这次变化。
useChatStreamScroll、useChatNewMessages 和 useAnnounce 从 @astryx-vue/core 导出。减少动效通过 useMediaQuery 读取。
输入套件另外导出 useChatComposerContext、useChatComposerTokens、useChatPasteAsToken、useChatDictation 和 useSpeechRecognition。它们从 Chat 子路径引入,包根也会再导出一份。语音识别只用浏览器接口,不绑定语音服务。长文本粘贴的默认阈值是 200 个字符。
主题
packages/themes/neutral/chat.css 把组件变量映射到语义 token。换主题时覆盖这些变量即可。
--astryx-chat-bubble-background/--astryx-chat-foreground:填充气泡的底色和文字,对应--astryx-color-neutral和--astryx-color-text-primary。--astryx-chat-foreground-secondary、--astryx-chat-foreground-muted:元信息、系统行、工具调用的次要文字。--astryx-chat-error、--astryx-chat-success、--astryx-chat-accent:失败状态、删除行数、进行中的工具。--astryx-chat-unread-color:未读分隔线的线和标签,Neutral 映射到--astryx-color-border-red,两条视口用同一个颜色。--astryx-chat-focus:折叠按钮的键盘焦点描边。--astryx-chat-scroll-background/--astryx-chat-scroll-shadow:回到底部的胶囊。--astryx-chat-radius:单独气泡的圆角。紧凑密度用--astryx-chat-radius-compact。成组气泡的内侧用--astryx-chat-radius-group。--astryx-duration-fast-max、--astryx-duration-medium-max、--astryx-duration-slow-max、--astryx-ease-standard:胶囊、折叠和输入中圆点的动效。
原生属性
ChatLayout、ChatMessageList、ChatMessage、ChatSystemMessage、ChatToolCalls、ChatReasoning、ChatTypingIndicator、ChatUnreadDivider、ChatComposer、ChatComposerDrawer、ChatComposerInput、ChatTokenizedText 把属性转到根节点。ChatMessageBubble 转到气泡,不转到名字或元信息。ChatMessageMetadata 转到元信息那一行。ChatSendButton 和 ChatDictationButton 转到按钮外层。