ChatPromptPRO

一个增强型的 Textarea 组件,用于在 AI 聊天界面中提交提示。

用法

ChatPrompt 组件渲染一个 <form> 元素,并扩展了 Textarea 组件,因此你可以传递任何属性,例如 iconplaceholderautofocus 等。

ChatPrompt 处理以下事件
  • 当用户按下 或点击提交按钮时,表单会被提交。
  • 当按下 时,文本域会失去焦点并触发一个 close 事件。

变体

使用 variant prop 来改变提示的样式。默认为 outline

<template>
  <UChatPrompt variant="soft" />
</template>

示例

这些聊天组件设计用于与 Vercel AI SDK 中的 useChat composable 函数一起使用。
在 GitHub 上查看我们的 AI 聊天模板 源代码,了解实际示例。

在页面中使用

将 ChatPrompt 组件与 useChat composable 函数一起使用,以在页面中显示聊天提示。

同时传递 input prop 和 error prop,以便在发生错误时禁用文本域。

pages/[id].vue
<script setup lang="ts">
import { useChat } from '@ai-sdk/vue'

const { messages, input, handleSubmit, reload, stop, status, error } = useChat()
</script>

<template>
  <UDashboardPanel>
    <template #body>
      <UContainer>
        <UChatMessages :messages="messages" :status="status">
          <template #content="{ message }">
            <MDC :value="message.content" :cache-key="message.id" unwrap="p" />
          </template>
        </UChatMessages>
      </UContainer>
    </template>

    <template #footer>
      <UContainer>
        <UChatPrompt v-model="input" :error="error" @submit="handleSubmit">
          <UChatPromptSubmit :status="status" @stop="stop" @reload="reload" />
        </UChatPrompt>
      </UContainer>
    </template>
  </UDashboardPanel>
</template>

你也可以将其作为聊天界面的起点。

pages/index.vue
<script setup lang="ts">
const input = ref('')
const loading = ref(false)

async function onSubmit() {
  loading.value = true

  const chat = await $fetch('/api/chats', {
    method: 'POST',
    body: { input }
  })

  navigateTo(`/chat/${chat.id}`)
}
</script>

<template>
  <UDashboardPanel>
    <template #body>
      <UContainer>
        <h1>How can I help you today?</h1>

        <UChatPrompt v-model="input" :status="loading ? 'streaming' : 'ready'" @submit="onSubmit">
          <UChatPromptSubmit />
        </UChatPrompt>
      </UContainer>
    </template>
  </UDashboardPanel>
</template>

API

属性 (Props)

属性默认值类型
as

'form'

any

autofocus

true

boolean

autoresize

true

boolean

rows

1

number

icon

string

根据 leadingtrailing prop 显示图标。

error

Error

modelValue

string

variant

'outline'

"outline" | "soft" | "subtle" | "naked"

loading

boolean

当为 true 时,将显示加载图标。

loadingIcon

appConfig.ui.icons.loading

string

loading prop 为 true 时显示的图标。

avatar

AvatarProps

在左侧显示一个头像。

placeholder

t('chatPrompt.placeholder')

string

文本域的占位符文本。

autofocusDelay

number

autoresizeDelay

number

maxrows

number

ui

{ root?: ClassNameValue; header?: ClassNameValue; body?: ClassNameValue; footer?: ClassNameValue; base?: ClassNameValue; } & { ...; }

插槽 (Slots)

插槽类型
header

{}

footer

{}

leading

{}

default

{}

trailing

{}

事件 (Emits)

事件类型
close

[event: Event]

submit

[event: Event]

update:modelValue

[value: string]

主题

app.config.ts
export default defineAppConfig({
  uiPro: {
    chatPrompt: {
      slots: {
        root: 'relative flex flex-col items-stretch gap-2 px-2.5 py-2 w-full rounded-lg backdrop-blur',
        header: 'flex items-center gap-1.5',
        body: 'items-start',
        footer: 'flex items-center justify-between gap-1.5',
        base: 'text-base/5'
      },
      variants: {
        variant: {
          outline: {
            root: 'bg-default/75 ring ring-default'
          },
          soft: {
            root: 'bg-elevated/50'
          },
          subtle: {
            root: 'bg-elevated/50 ring ring-default'
          },
          naked: {
            root: ''
          }
        }
      },
      defaultVariants: {
        variant: 'outline'
      }
    }
  }
})
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({
      uiPro: {
        chatPrompt: {
          slots: {
            root: 'relative flex flex-col items-stretch gap-2 px-2.5 py-2 w-full rounded-lg backdrop-blur',
            header: 'flex items-center gap-1.5',
            body: 'items-start',
            footer: 'flex items-center justify-between gap-1.5',
            base: 'text-base/5'
          },
          variants: {
            variant: {
              outline: {
                root: 'bg-default/75 ring ring-default'
              },
              soft: {
                root: 'bg-elevated/50'
              },
              subtle: {
                root: 'bg-elevated/50 ring ring-default'
              },
              naked: {
                root: ''
              }
            }
          },
          defaultVariants: {
            variant: 'outline'
          }
        }
      }
    })
  ]
})
vite.config.ts
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import uiPro from '@nuxt/ui-pro/vite'

export default defineConfig({
  plugins: [
    vue(),
    uiPro({
      uiPro: {
        chatPrompt: {
          slots: {
            root: 'relative flex flex-col items-stretch gap-2 px-2.5 py-2 w-full rounded-lg backdrop-blur',
            header: 'flex items-center gap-1.5',
            body: 'items-start',
            footer: 'flex items-center justify-between gap-1.5',
            base: 'text-base/5'
          },
          variants: {
            variant: {
              outline: {
                root: 'bg-default/75 ring ring-default'
              },
              soft: {
                root: 'bg-elevated/50'
              },
              subtle: {
                root: 'bg-elevated/50 ring ring-default'
              },
              naked: {
                root: ''
              }
            }
          },
          defaultVariants: {
            variant: 'outline'
          }
        }
      }
    })
  ]
})