聊天推理 (ChatReasoning)

CollapsibleGitHub
显示可折叠的 AI 推理或思考过程。

用法

ChatReasoning 组件渲染一个可折叠区块,用于显示 AI 的推理或思考过程。它在流式传输期间会自动展开,结束后自动收起。

<script setup lang="ts">
const streaming = ref(false)
const text = ref('')

async function simulateStreaming() {
  streaming.value = true
  text.value = ''

  const content =
    'The user is asking about Vue components. I should explain the Composition API pattern and how it relates to their question about reactive state management. Let me think about the best way to structure this response.\n\nFirst, I need to consider the key differences between the Options API and Composition API. The Composition API was introduced in Vue 3 to address limitations of the Options API when building large-scale applications.\n\nFor reactive state management specifically, the Composition API offers ref() for primitive values and reactive() for objects.'

  for (const char of content) {
    text.value += char
    await new Promise((resolve) => setTimeout(resolve, 10))
  }

  streaming.value = false
}

onMounted(simulateStreaming)
</script>

<template>
  <UChatReasoning :text="text" :streaming="streaming" class="w-60" />
</template>
<script setup lang="ts">
import { ref, reactive, onMounted } from 'vue'

const streaming = ref(false)
const text = ref('')

async function simulateStreaming() {
  streaming.value = true
  text.value = ''

  const content =
    'The user is asking about Vue components. I should explain the Composition API pattern and how it relates to their question about reactive state management. Let me think about the best way to structure this response.\n\nFirst, I need to consider the key differences between the Options API and Composition API. The Composition API was introduced in Vue 3 to address limitations of the Options API when building large-scale applications.\n\nFor reactive state management specifically, the Composition API offers ref() for primitive values and reactive() for objects.'

  for (const char of content) {
    text.value += char
    await new Promise((resolve) => setTimeout(resolve, 10))
  }

  streaming.value = false
}

onMounted(simulateStreaming)
</script>

<template>
  <UChatReasoning :text="text" :streaming="streaming" class="w-60" />
</template>
正文内容使用 useScrollShadow 可组合函数,在内容溢出时应用淡入阴影效果。

文本

使用 text prop 来设置推理内容。文本将显示在可折叠的主体中。

<template>
  <UChatReasoning text="The user is asking about Vue components..." />
</template>

流式传输 (Streaming)

使用 streaming prop 来指示当前正在进行推理。组件会在流式传输开始时自动展开,并在结束时自动收起。

用户正在询问有关 Vue 组件的问题……
<template>
  <UChatReasoning streaming text="The user is asking about Vue components..." />
</template>
使用来自 @nuxt/ui/utils/aiisPartStreaming 工具来判断某个部分当前是否正在进行流式传输。

Shimmer 效果

在流式传输时,触发器标签会使用 ChatShimmer 组件。使用 shimmer prop 来自定义其 durationspread

用户正在询问有关 Vue 组件的问题……
<template>
  <UChatReasoning
    streaming
    text="The user is asking about Vue components..."
    :shimmer="{
      duration: 2,
      spread: 2
    }"
  />
</template>

Icon

使用 icon prop 在触发器旁边显示一个 Icon 组件。

<template>
  <UChatReasoning icon="i-lucide-brain" text="The user is asking about Vue components..." />
</template>

折叠图标 (Chevron)

使用 chevron prop 来更改折叠图标的位置。

chevron 设置为 leading 且有 icon 时,图标会在悬停或打开状态时与折叠图标交换位置。
<template>
  <UChatReasoning
    chevron="leading"
    icon="i-lucide-brain"
    text="The user is asking about Vue components..."
  />
</template>

折叠图标

使用 chevron-icon prop 自定义折叠 Icon。默认为 i-lucide-chevron-down

<template>
  <UChatReasoning
    chevron-icon="i-lucide-arrow-down"
    text="The user is asking about Vue components..."
  />
</template>
您可以在 app.config.ts 中通过 ui.icons.chevronDown 键全局自定义此图标。
您可以在 vite.config.ts 中通过 ui.icons.chevronDown 键全局自定义此图标。

示例

查看 Chat 概览页面以获取安装说明、服务器设置和使用示例。

API

属性

属性默认值类型
文本string

要显示的推理文本内容。

streamingfalseboolean

推理内容当前是否正在进行流式传输。

durationnumber

AI 进行推理所花费的时间(以秒为单位)。如果未提供,将根据流式传输时间自动计算。

图标any

显示在触发器旁边的图标。

chevron'trailing'"leading" | "trailing"

折叠图标的位置。

chevronIconappConfig.ui.icons.chevronDownany

用作折叠箭头的图标。

autoCloseDelay500number

流式传输结束后自动收起的延迟时间(以毫秒为单位)。设置为 0 可禁用自动收起。

shimmerPartial<Omit<ChatShimmerProps, "text">>

流式传输时自定义 ChatShimmer 组件。

disabledboolean

当设置为 true 时,禁止用户与折叠块进行交互。

openundefinedboolean

折叠块的受控展开状态。可以通过 v-model 进行绑定。

defaultOpenboolean

折叠块在初始渲染时的展开状态。
当您不需要控制其打开状态时使用。

unmountOnHidefalseboolean

当为 `true` 时,元素在关闭状态下将被卸载。

ui{ root?: SlotClass; trigger?: SlotClass; leading?: SlotClass; leadingIcon?: SlotClass; chevronIcon?: SlotClass; label?: SlotClass; trailingIcon?: SlotClass; content?: SlotClass; body?: SlotClass; }

插槽

插槽类型
default{ open: boolean; }

事件

事件类型
update:open[value: boolean]

主题

app.config.ts
export default defineAppConfig({
  ui: {
    chatReasoning: {
      slots: {
        root: '',
        trigger: [
          'group flex w-full items-center gap-1.5 text-muted text-sm disabled:cursor-default disabled:hover:text-muted hover:text-default rounded-sm outline-primary/25 focus-visible:outline-3 min-w-0',
          'transition-colors'
        ],
        leading: 'relative size-4 shrink-0',
        leadingIcon: 'size-4 shrink-0',
        chevronIcon: 'size-4 shrink-0 group-data-[state=open]:rotate-180 transition-transform duration-200',
        label: 'truncate',
        trailingIcon: 'size-4 shrink-0 group-data-[state=open]:rotate-180 transition-transform duration-200',
        content: 'data-[state=open]:animate-[collapsible-down_200ms_ease-out] data-[state=closed]:animate-[collapsible-up_200ms_ease-out] data-[state=closed]:overflow-hidden rounded-sm outline-primary/25 has-focus-visible:outline-3',
        body: 'max-h-[200px] pt-2 overflow-y-auto text-sm text-dimmed whitespace-pre-wrap focus:outline-none'
      },
      variants: {
        chevron: {
          leading: {
            leadingIcon: 'group-hover:opacity-0'
          },
          trailing: ''
        },
        alone: {
          false: {
            leadingIcon: [
              'absolute inset-0 group-data-[state=open]:opacity-0',
              'transition-opacity duration-200'
            ],
            chevronIcon: [
              'absolute inset-0 opacity-0 group-hover:opacity-100 group-data-[state=open]:opacity-100',
              'transition-[rotate,opacity] duration-200'
            ]
          }
        }
      }
    }
  }
})
vite.config.ts
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import ui from '@nuxt/ui/vite'

export default defineConfig({
  plugins: [
    vue(),
    ui({
      ui: {
        chatReasoning: {
          slots: {
            root: '',
            trigger: [
              'group flex w-full items-center gap-1.5 text-muted text-sm disabled:cursor-default disabled:hover:text-muted hover:text-default rounded-sm outline-primary/25 focus-visible:outline-3 min-w-0',
              'transition-colors'
            ],
            leading: 'relative size-4 shrink-0',
            leadingIcon: 'size-4 shrink-0',
            chevronIcon: 'size-4 shrink-0 group-data-[state=open]:rotate-180 transition-transform duration-200',
            label: 'truncate',
            trailingIcon: 'size-4 shrink-0 group-data-[state=open]:rotate-180 transition-transform duration-200',
            content: 'data-[state=open]:animate-[collapsible-down_200ms_ease-out] data-[state=closed]:animate-[collapsible-up_200ms_ease-out] data-[state=closed]:overflow-hidden rounded-sm outline-primary/25 has-focus-visible:outline-3',
            body: 'max-h-[200px] pt-2 overflow-y-auto text-sm text-dimmed whitespace-pre-wrap focus:outline-none'
          },
          variants: {
            chevron: {
              leading: {
                leadingIcon: 'group-hover:opacity-0'
              },
              trailing: ''
            },
            alone: {
              false: {
                leadingIcon: [
                  'absolute inset-0 group-data-[state=open]:opacity-0',
                  'transition-opacity duration-200'
                ],
                chevronIcon: [
                  'absolute inset-0 opacity-0 group-hover:opacity-100 group-data-[state=open]:opacity-100',
                  'transition-[rotate,opacity] duration-200'
                ]
              }
            }
          }
        }
      }
    })
  ]
})

更新日志

暂无近期更新