跳转到内容

Reasoning 思考过程 alpha

模型的推理片段:默认随写入自动展开,完成后自动收起,用户手动操作过一次后不再自动开合。

用法

思考时自动展开、思考完成后自动收起;状态文案由组件按是否在思考与时长给出

组件结构

加粗的是必需部件。

data-scope="reasoning"root · trigger · icon · indicator · label · duration · content

示例

无壳内联形态

ghost 档不占用一块面,开关收为只占文字宽度的小药丸,适合在一段回答中穿插多处

把两处思考穿插在同一段回答里,它们不再各自占一张卡:

语气与尺寸

tone 切换指示符与状态文案的色族,size 切换标题行与正文的几何档;五份都处于思考中,正文自动展开

success:先看约束,再看目标。
warning:先看约束,再看目标。
danger:先看约束,再看目标。
sm:先看约束,再看目标。
lg:先看约束,再看目标。

受控开合与禁用

open 交给宿主:外部一个按钮统一开合几段思考,自动开合让位;disabled 的一段开关不可按下,停在给定的档位

先确认这次只改皮肤:解剖与事件都不动,公开面就只增不减。

设计指引

何时使用

  • 展示推理模型输出的思考过程,且它边生成边显示。
  • 希望读者可以回看推理过程,但默认不占版面。

何时不用

  • 展示一次工具调用时,使用工具调用,两者共用同一台状态机但正文形态不同。
  • 内容不是散文而是结构化数据时,属于工具调用的参数与结果。

特性

  • 自动开合与工具调用是同一台状态机:锁存依靠转移的放置位置,不依靠布尔位,用户点击过一次之后阶段变化就不再触发自动开合。
  • 思考时长由两个时刻计算,任一缺席即无法计算:流被中止时兜底收尾不写结束时刻,推理块只有起点没有终点,这一情况必须被处理。
  • 名称与时长都排在开关内,“思考过程,用时 12 秒”整句构成开关的可访问名称。
  • 状态文案由组件提供:进行中显示“在想”的文案,完成后把秒数代入 thoughtFor{seconds},无法计算时长时回落到折叠区的名称。名称位不写内容时显示的就是它。
  • 形态三档:outline 描边、subtle 底色分区(默认档)、ghost 无壳内联。一段回答中穿插多处思考时使用 ghost,它不占一块面,开关收为只占文字宽度的小圆角块。
  • 开合有动画:展开与收起是行高与内缩同帧动画,收起在动画完成后才真正隐藏。

组合

  • 正文使用流式正文:思考过程是散文,与工具调用的等宽结构块不同。正文放在一个容器内:展开动画测量的是第一行的行高,散落的多个兄弟节点无法正确收起。
  • 多段推理并排且一次只展开一段时使用手风琴
  • 需要让“进行中 → 完成”被读屏播报时,把会话级的活动区域放在推理块外,由它读出结果。

最佳实践

  • 完成后显示时长,读者据此判断是否值得展开。
  • 默认收起。思考过程是给需要查看的人看的,不是回答本身。

反模式

  • 把思考过程当作回答显示:两者混在一起时读者分不清结论。
  • 用它承载工具调用的参数与结果:正文排版是散文形态,等宽结构块会挤在一起。

API 参考

产物

自定义元素<xh-reasoning>
Vue 组件XhReasoningContent XhReasoningDuration XhReasoningIcon XhReasoningIndicator XhReasoningLabel XhReasoningRoot XhReasoningTrigger
组合式函数useReasoning
状态机无,connect 直接由 props 算属性
皮肤@xihan-ui/styles/reasoning.css

Props

属性类型必填说明
endTimenumber思考结束的时刻。可能缺席:流被中止时兜底收尾不写该字段。
sizeSize
startTimenumber开始思考的时刻,毫秒时间戳。
streamingboolean仍在思考。适配器把它折叠为状态机的 running。
toneTone
translationsPartial<ReasoningTranslations>
variantControlVariant形态:outline 描边、subtle 底色分区、ghost 无壳内联。默认 subtle。

事件

自定义元素将载荷放在 detail;Vue 使用同名 emit。

事件载荷说明
open-changeToolCallOpenChangeDetails开合变化;detail 为 { open: boolean, source: 'user' | 'auto' | 'api' }

插槽

仅列出带载荷的插槽。

Vue 组件插槽载荷说明
XhReasoningRootdefaultReasoningRootSlotProps

状态

公开状态写入 data-state

部件取值
root'open' | 'closed'
trigger'open' | 'closed'
indicator'open' | 'closed'
content'open' | 'closed'

connect API

getXxxProps() 返回对应部件的宿主属性。

成员类型说明
openboolean
streamingboolean
disabledboolean
durationMsnumber | undefined思考时长,毫秒;两个时刻任一缺席即 undefined。
statusTextstring当前应显示的状态文案,已按 streaming 与时长选定。
setOpen(next: boolean) => void
getRootProps() => T['element']
getTriggerProps() => T['button']
getIconProps() => T['element']
getIndicatorProps() => T['element']
getLabelProps() => T['element']
getDurationProps() => T['element']
getContentProps() => T['element']

无障碍

键盘

规格出处:W3C APG

按键生效条件行为
Enter / Space焦点在折叠开关上且未禁用展开或收起思考正文,并把自动开合永久停用
Enter / Space按住折叠开关且未禁用按住期间 trigger 投影 data-pressed,与指针 :active 同一副按压面(disclosure trigger 只换面不缩放);抬起、失焦或转禁用撤下。思考中照常接

ARIA

以下属性由 connect 生成。

部件属性
triggeraria-controlscontent 部件的 id
triggeraria-expanded'true' | 'false'
iconaria-hidden'true'
indicatoraria-hidden'true'
contentaria-labelledbytrigger 部件的 id
contentrole'region'
  • 开关带 aria-expandedaria-controls,正文区是 role=region 且由开关命名。
  • 不另发 aria-label:另发会覆盖节点内的文字,两者不一致时读屏读出的与屏幕不符。
  • 组件自身不开活动区域:整段思考每来一个字都播报会淹没读屏。

样式参考

皮肤

@xihan-ui/styles/reasoning.css 使用 [data-scope="reasoning"][data-part="root"] 部件选择器,位于 xihan.componentsxihan.motion 层。覆盖样式使用 xihan.overrides

forced-colors: active 下另有一套规则:颜色交给系统,边框与状态标记改用系统色关键字。

数据属性

connect 生成;条件不成立时不输出无值属性。

部件属性
rootdata-disabled''(条件成立时才出现)
rootdata-sizeprops.size
rootdata-state'open' | 'closed'
rootdata-streaming''(条件成立时才出现)
rootdata-toneprops.tone
rootdata-variantprops.variant
triggerdata-disabled''(条件成立时才出现)
triggerdata-pressed''(条件成立时才出现)
triggerdata-state'open' | 'closed'
triggerdata-streaming''(条件成立时才出现)
triggerdata-xh-action-control''
triggerdata-xh-action-display'always'
triggerdata-xh-action-profile'disclosure-trigger'
triggerdata-xh-action-sizeprops.size
triggerdata-xh-action-variant'ghost'
icondata-streaming''(条件成立时才出现)
indicatordata-state'open' | 'closed'
labeldata-streaming''(条件成立时才出现)
durationdata-streaming''(条件成立时才出现)
contentdata-state'open' | 'closed'

CSS 变量

本组件公开覆盖槽由独立皮肤的实际消费位生成;默认来源、作用部件和状态均与 CSS 同源。

变量部件CSS 属性状态默认来源说明
--xh-reasoning-bgrootbackgrounddefault
variant=outline
--xh-bg-subtle
--xh-bg-surface
reasoning 的 root 部件 background 覆盖槽。
--xh-reasoning-borderrootbordervariant=outline--xh-border-defaultreasoning 的 root 部件 border 覆盖槽。
--xh-reasoning-content-fgcontentcolordefault--xh-fg-mutedreasoning 的 content 部件 color 覆盖槽。
--xh-reasoning-content-font-sizecontentfont-sizedefault--xh-text-secondary-sizereasoning 的 content 部件 font-size 覆盖槽。
--xh-reasoning-content-leadingcontentline-heightdefault--xh-text-prose-leadingreasoning 的 content 部件 line-height 覆盖槽。
--xh-reasoning-content-pecontentpadding-inline-enddefault--xh-reasoning-pxreasoning 的 content 部件 padding-inline-end 覆盖槽。
--xh-reasoning-content-pscontentpadding-inline-startdefault--xh-space-3reasoning 的 content 部件 padding-inline-start 覆盖槽。
--xh-reasoning-duration-fgdurationcolordefault--xh-fg-subtlereasoning 的 duration 部件 color 覆盖槽。
--xh-reasoning-duration-font-sizedurationfont-sizedefault--xh-text-caption-sizereasoning 的 duration 部件 font-size 覆盖槽。
--xh-reasoning-font-sizetriggerfont-sizedefault--xh-_reasoning-font-sizereasoning 的 trigger 部件 font-size 覆盖槽。
--xh-reasoning-icon-fgiconcolordefault--xh-fg-subtlereasoning 的 icon 部件 color 覆盖槽。
--xh-reasoning-icon-sizeroot--xh-icon-sizedefault--xh-_reasoning-icon-sizereasoning 的 root 部件 --xh-icon-size 覆盖槽。
--xh-reasoning-icon-streaming-fgiconcolorstreaming--xh-fg-mutedreasoning 的 icon 部件 color 覆盖槽。
--xh-reasoning-indicator-fgindicatorcolordefault--xh-fg-subtlereasoning 的 indicator 部件 color 覆盖槽。
--xh-reasoning-label-font-weightlabelfont-weightdefault--xh-text-label-weightreasoning 的 label 部件 font-weight 覆盖槽。
--xh-reasoning-label-streaming-fglabelcolor@media (prefers-reduced-motion: reduce)
@media print
motion=reduce
streaming
where([data-motion='reduce'])
--xh-fg-defaultreasoning 的 label 部件 color 覆盖槽。
--xh-reasoning-pxcontent
trigger
margin-inline-start
padding-inline
padding-inline-end
default--xh-_reasoning-pxreasoning 的 content、trigger 部件 margin-inline-start、padding-inline、padding-inline-end 覆盖槽。
--xh-reasoning-pycontent
trigger
padding-block
padding-block-end
@keyframes xh-disclosure-collapse
@keyframes xh-disclosure-expand
default
xh-action-profile=disclosure-trigger
--xh-_reasoning-pyreasoning 的 content、trigger 部件 padding-block、padding-block-end 覆盖槽。
--xh-reasoning-radiusrootborder-radiusdefault--xh-shape-surfacereasoning 的 root 部件 border-radius 覆盖槽。
--xh-reasoning-railcontentborder-inline-startdefault--xh-border-subtlereasoning 的 content 部件 border-inline-start 覆盖槽。
--xh-reasoning-rail-insetcontentmargin-inline-startdefault--xh-reasoning-pxreasoning 的 content 部件 margin-inline-start 覆盖槽。
--xh-reasoning-rail-widthcontentborder-inline-startdefault--xh-stroke-thinreasoning 的 content 部件 border-inline-start 覆盖槽。
--xh-reasoning-shadowrootbox-shadowdefault
tone
0 0 0 transparent
none
reasoning 的 root 部件 box-shadow 覆盖槽。
--xh-reasoning-shimmer-durationlabelanimationstreaming--xh-shimmer-durationreasoning 的 label 部件 animation 覆盖槽。
--xh-reasoning-shimmer-fromlabelbackground-imagestreaming--xh-fg-subtlereasoning 的 label 部件 background-image 覆盖槽。
--xh-reasoning-shimmer-tolabelbackground-imagestreaming--xh-fg-defaultreasoning 的 label 部件 background-image 覆盖槽。
--xh-reasoning-tone-barrootbox-shadowtone--xh-stroke-thickreasoning 的 root 部件 box-shadow 覆盖槽。
--xh-reasoning-tone-fgrootbox-shadowtone--xh-_tone-softreasoning 的 root 部件 box-shadow 覆盖槽。
--xh-reasoning-trigger-bg-hovertriggerbackground-colordisabled
hover
loading
not([data-disabled])
not([data-loading])
--xh-_action-variant-bg-hoverreasoning 的 trigger 部件 background-color 覆盖槽。
--xh-reasoning-trigger-fgtriggercolordefault
disabled
hover
is(:active, [data-pressed])
loading
not([data-disabled])
not([data-loading])
pressed
--xh-fg-mutedreasoning 的 trigger 部件 color 覆盖槽。
--xh-reasoning-trigger-gaptriggergapdefault--xh-space-2reasoning 的 trigger 部件 gap 覆盖槽。
--xh-reasoning-trigger-radiusroot
trigger
border-radiusvariant=ghost--xh-shape-controlreasoning 的 root、trigger 部件 border-radius 覆盖槽。

动效

关键帧 xh-reasoning-fade-in · xh-reasoning-shimmer 随皮肤自带,不引用别处文件里的名字;共享关键帧 xh-disclosure-collapse · xh-disclosure-expandfamily/motion.css 提供,皮肤 @import 它,单独引入仍成立;color · rotatetransition 过渡。时长与缓动读动效令牌,改令牌即改全局节奏。

皮肤之外还有一段:退场由适配器的退场闸门把关,动画播完才真收起。

prefers-reduced-motion: reduce 下本组件另有降级规则。

RTL

皮肤用逻辑属性排布(inline-start 一族),dir="rtl" 下自动镜像。

Released under The MIT License