Skip to content

对话

ChatLayout ​

名称类型默认值说明
density'compact' | 'balanced' | 'spacious''balanced'间距、气泡宽度和底部磨砂。单条消息可以自己覆盖。
scrollRefHTMLElement | null-代替布局自己滚动的元素。不传时由布局滚动。自己滚动时底部停靠是 sticky,外部滚动时改成 fixed。
showScrollButtonbooleantrue是否渲染内置的回到底部按钮。用 scrollButton 插槽替换,或者根本不需要这个按钮时设为 false。
名称说明
default会话记录,通常放一个 ChatMessageList。
composer贴在底部,位于磨砂层之上。
empty没有默认插槽时显示。
scrollButton替换内置按钮。参数:isVisible、label(只在有未读新消息时有值)、scrollToBottom。

模板引用暴露 element 和 scrollToBottom()。scrollToBottom 会清掉「有新消息」,再用弹簧滚到底部。

ChatLayoutScrollButton ​

名称类型默认值说明
isVisibleboolean-胶囊是否可见。隐藏时仍挂在树上,方便淡出,并带 inert。
labelstring-把胶囊拉宽。不传时只有向下的图标。无障碍名称回退到「滚动到底部」。

按下按钮时发出 click。

ChatMessageList ​

名称类型默认值说明
align'top' | 'bottom''bottom'消息不到一屏时贴顶还是贴底。'bottom' 在消息前面留一块弹性空白;'top' 不留,消息从顶上排。
density'compact' | 'balanced' | 'spacious''balanced'传给没有自己设置密度的消息。
gapSpacingStep-顶层行之间的间距,走间距刻度。只改间距,不改内边距。
scrollToTopAction() => Promise<void>-顶部哨兵进入滚动容器时加载更早的消息。Promise 结束前显示加载指示。上一次还没结束时,再次进入不会重复触发。
isStreamingbooleanfalse助手消息还在增长时设置 aria-busy。
labelstring本地化的「消息列表」日志的无障碍名称。

default 插槽是各行。emptyState 在没有 default 时显示,empty 是它的别名。根节点是 role="log",aria-live="polite"。

ChatMessage ​

名称类型默认值说明
sender'user' | 'assistant' | 'system'-这条消息是谁发的。system 居中,头像、名字和元信息都忽略。
namestring-纯文本名字。正文以气泡开头时,更适合把名字放在气泡上。
density'compact' | 'balanced' | 'spacious'先看列表,再回退到 'balanced'只作用于这一行的密度。

插槽:default(正文)、avatar、name(替换属性)、metadata。article 的名称优先用可见名字,否则是「来自{发送者}的消息」。

ChatMessageBubble ​

名称类型默认值说明
variant'filled' | 'ghost''filled'filled 有发送者底色。ghost 去掉背景和上下内边距,混排内容仍然对齐。
namestring-与气泡内边距对齐的名字。
group'first' | 'middle' | 'last'-多条气泡叠在一起时收紧一角。单独一条不用传。

发送者和密度来自外层 ChatMessage。插槽:default、name、metadata。属性落到气泡元素上。

ChatMessageMetadata ​

名称类型默认值说明
timestampstring-时间等短文本。timestamp 插槽会替换它。
footerstring-次要文字,例如模型名。footer 插槽会替换它。
status'sending' | 'sent' | 'delivered' | 'read' | 'error'-投递状态。时间、补充文字和状态都没有时,这一行不渲染。

状态图标的无障碍名称会本地化,例如「消息已读」。用户消息上,各项从行尾开始排。

ChatSystemMessage ​

名称类型默认值说明
variant'default' | 'divider''default'default 是居中的一行。divider 两侧各有一条线。根节点是 role="status"。

插槽:default,以及 icon(divider 时忽略)。

ChatToolCalls ​

名称类型默认值说明
callsChatToolCallItem[]-一轮回复里的工具调用。空数组不渲染。每项可以带 name、status、target、duration、node、additions、deletions、stats、errorMessage、key、resultDetail、data。detail 是 resultDetail 的别名。
labelstring本地化的「{count} 个工具调用」分组展开时的标题。
v-model:isExpandedboolean-多条调用这一组的受控展开状态。
defaultIsExpandedbooleanfalseisExpanded 未绑定时的初始状态。

发出 expandedChange,参数是下一个布尔值。detail 插槽收到 { call },用来替换 call.resultDetail。分组收起时只显示最新一条;面板在打开前是 inert。等待中和进行中用加载指示。错误会放进一段视觉隐藏的文字里读出来。

ChatReasoning ​

名称类型默认值说明
labelstring本地化的「思考中」标题。
durationstring-流式结束后跟在标题后面,例如 12s。
isStreamingbooleanfalse标题闪动,并藏起预览和耗时。
v-model:isExpandedboolean-受控展开状态。
defaultIsExpandedbooleanfalseisExpanded 未绑定时的初始状态。

默认插槽是完整推理。只有一个文本节点时,它也是收起状态的预览。发出 expandedChange。收起时面板是 inert。

ChatTypingIndicator ​

名称类型默认值说明
namesstring[]-正在输入的人。空字符串会被丢掉。不传名字时只有三个点。一个人、两个人、三个及以上各有一句文案。

根节点是 role="status",并带 aria-live="polite"。文案就写在这个区域里,不再经 useAnnounce 播第二遍。

ChatUnreadDivider ​

名称类型默认值说明
labelstring本地化的「新消息」线末端的短标签。无障碍名称是「{label}以下是未读消息」。

根节点是 role="separator"。它没有 .astryx-chat-message,新消息追踪不会把它当成一条消息。

ChatComposer ​

名称类型默认值说明
modelValuestring-受控草稿,用 v-model 绑定。不传时由外壳自己保存。
placeholderstring当前语言的「输入消息……」草稿为空时的占位文字。
isDisabledbooleanfalse停用编辑和发送。正在生成时如果显示停止,停止按钮仍然可以点。
density'compact' | 'balanced' | 'spacious''balanced'外壳内边距。宽松和均衡用同一套间距。
elevation'low' | 'none''low'低阴影在悬停和焦点时加深。none 是平的,靠边框区分。只有键盘把焦点放进编辑器时才画出焦点环。
isStopShownbooleanfalse用停止代替发送。
status{ type: 'error' | 'warning', message?: string }-错误用 alert,警告用 status。
statusPosition'top' | 'bottom''bottom'状态条贴在外壳上方或下方,并伸进圆角后面。
名称参数说明
submitvalue: string草稿去掉首尾空白后仍有内容时发出,然后清空草稿。
stop-停止被点下。
changevalue: string草稿变化,包括发送后的清空。
update:modelValuevalue: string和 change 一起发出,给 v-model 用。

插槽有 drawer、headerActions、headerContext、input、footerActions、sendActions、sendButton。模板引用暴露 element。

ChatComposerInput ​

名称类型默认值说明
modelValuestring-单独受控时使用。放在外壳里且不传时,跟外壳的草稿走。
placeholderstring外壳或当前语言的占位空编辑器上的提示。
maxRowsnumber8超过这么多行后开始内部滚动。一行按 22px 算。
triggersChatComposerTrigger[]-在词首输入触发字符时打开建议列表。触发器上的 hasMultiWordQuery 让查询穿过空格和标点,直到换行、超过 64 个字符,或同一个触发字符再次出现。不设时,空格或制表符结束查询。多词查询没有匹配、也没写 emptySearchText 时,列表先藏起来。有触发器时编辑器是 combobox。
debounceMsnumber150异步搜索的等待。同步结果不延迟,第一次异步搜索立刻开始。
hasHistorybooleantrue光标在开头时上方向键取回上一条已发送草稿,在末尾时下方向键往回走。
labelstring当前语言的「消息输入框」编辑器的无障碍名称。
isDisabledboolean外壳的停用状态停用编辑。
pasteAsTokenuseChatPasteAsToken 的返回值 | false超过 200 字变成标记传 false 时长文本按原文插入。
pasteAction(event, text) => boolean | void-纯文本粘贴的第一站。返回 true 时输入框不再自己插入。

事件有 change、update:modelValue、submit、files、keydown。files 来自粘贴或拖入的文件,拖入不会让浏览器打开文件。keydown 在建议列表处理完之后发出,preventDefault 会跳过回车发送和历史。模板引用上有 insertToken、expandToken、insertText、focus、getValue。

ChatComposerDrawer ​

名称类型默认值说明
countnumber-传入后才能折叠,并显示在默认摘要里。
labelstring当前语言的「项目」摘要和展开、折叠的无障碍名称都用它。
isCollapsedboolean-受控折叠,用 v-model:is-collapsed。
defaultIsCollapsedbooleanfalse未绑定时的初始状态。

collapsedChange 在折叠状态变化时发出。默认插槽是展开后的内容。collapsedSummary 替换计数和名称,按钮自己仍带无障碍名称。

ChatSendButton ​

名称类型默认值说明
isStopShownboolean外壳的停止状态停止用次要按钮,发送用主要按钮。停止不受停用影响。
isDisabledboolean草稿为空或外壳停用只停用发送。
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 转到按钮外层。