聊天推理

显示可折叠的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>
body内容使用useScrollShadow组合工具在溢出时应用渐变阴影。

Text

使用text属性设置推理内容,文本显示在可折叠的正文中。

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

流媒体

使用streaming prop来表示主动推理。该组件在流式传输开始时自动打开,在流式传输结束时自动关闭。

The user is asking about Vue components...
<template>
  <UChatReasoning streaming text="The user is asking about Vue components..." />
</template>
使用@nuxt/ui/utils/ai中的isPartStreaming实用程序确定当前是否正在流式传输部件。

Shimmer

在流式传输时,触发器标签使用ChatShimmer组件。使用shimmer道具可以自定义其duration和spread。

The user is asking about Vue components...
<template>
  <UChatReasoning
    streaming
    text="The user is asking about Vue components..."
    :shimmer="{
      duration: 2,
      spread: 2
    }"
  />
</template>

Icon

使用icon道具在触发器旁边显示Icon组件。

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

雪佛龙

使用chevron道具改变V形图标的位置。

当chevron被设置为leading和icon时,图标在悬停和打开时与V形符号交换。
<template>
  <UChatReasoning
    chevron="leading"
    icon="i-lucide-brain"
    text="The user is asking about Vue components..."
  />
</template>

Chevron图标

使用chevron-icon道具将chevron Icon.exe自定义为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键下全局自定义这个图标。
你可以在你的ui.icons.chevronDown键下的vite.config.ts中全局自定义这个图标。

示例

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

API

Props

Prop Default Type
text
string

The reasoning text content to display.

streaming
false
boolean

Whether the reasoning content is currently streaming.

duration
number

The duration in seconds that the AI spent reasoning. If not provided, it will be calculated automatically based on streaming time.

icon
any

The icon displayed next to the trigger.

chevron
'trailing'
"leading" | "trailing"

The position of the chevron icon.

chevronIcon
appConfig.ui.icons.chevronDown
any

The icon displayed as the chevron.

autoCloseDelay
500
number

The delay in milliseconds before auto-closing when streaming ends. Set to 0 to disable auto-close.

shimmer
Partial<Omit<ChatShimmerProps, "text">>

Customize the ChatShimmer component when streaming.

disabled
boolean

When true, prevents the user from interacting with the collapsible.

open
undefined
boolean

The controlled open state of the collapsible. Can be binded with v-model.

defaultOpen
boolean

The open state of the collapsible when it is initially rendered.
Use when you do not need to control its open state.

unmountOnHide
false
boolean

When true, the element will be unmounted on closed state.

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

Slots

Slot Type
default
{ open: boolean; }

发射

Event Type
update:open
[value: boolean]

Theme

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 ease-out motion-reduce:transition-none',
        label: 'truncate',
        trailingIcon: 'size-4 shrink-0 group-data-[state=open]:rotate-180 transition-transform duration-200 ease-out motion-reduce:transition-none',
        content: 'data-[state=open]:animate-[collapsible-down_200ms_var(--ease-out)] data-[state=closed]:animate-[collapsible-up_200ms_var(--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 ease-out'
            ],
            chevronIcon: [
              'absolute inset-0 opacity-0 group-hover:opacity-100 group-data-[state=open]:opacity-100',
              'transition-[rotate,opacity] duration-200 ease-out motion-reduce:transition-none'
            ]
          }
        }
      }
    }
  }
})
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 ease-out motion-reduce:transition-none',
            label: 'truncate',
            trailingIcon: 'size-4 shrink-0 group-data-[state=open]:rotate-180 transition-transform duration-200 ease-out motion-reduce:transition-none',
            content: 'data-[state=open]:animate-[collapsible-down_200ms_var(--ease-out)] data-[state=closed]:animate-[collapsible-up_200ms_var(--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 ease-out'
                ],
                chevronIcon: [
                  'absolute inset-0 opacity-0 group-hover:opacity-100 group-data-[state=open]:opacity-100',
                  'transition-[rotate,opacity] duration-200 ease-out motion-reduce:transition-none'
                ]
              }
            }
          }
        }
      }
    })
  ]
})

Changelog

No recent changes