Usage
The ChatPrompt component renders a <form>
element and extends the Textarea component so you can pass any property such as icon
, placeholder
, autofocus
, etc.
- The form is submitted when the user presses ↵ or when the user clicks on the submit button.
- The textarea is blurred when ⎋ is pressed and emits a
close
event.
Variant
Use the variant
prop to change the style of the prompt. Defaults to outline
.
<template>
<UChatPrompt variant="soft" />
</template>
Examples
Within a page
Use the ChatPrompt component with the useChat
composable to display a chat prompt within a page.
Pass the input
prop alongside the error
prop to disable the textarea when an error occurs.
<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>
You can also use it as a starting point for a chat interface.
<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
Prop | Default | Type |
---|---|---|
as |
|
|
autofocus |
|
|
autoresize |
|
|
rows |
|
|
icon |
Display an icon based on the | |
error |
| |
modelValue |
| |
avatar |
Display an avatar on the left side.
| |
variant |
|
|
loading |
When | |
loadingIcon |
|
The icon when the |
placeholder |
|
The placeholder text for the textarea. |
autofocusDelay |
| |
autoresizeDelay |
| |
maxrows |
| |
ui |
|
Slots
Slot | Type |
---|---|
header |
|
footer |
|
leading |
|
default |
|
trailing |
|
Emits
Event | Type |
---|
Theme
export default defineAppConfig({
uiPro: {
chatPrompt: {
slots: {
root: 'relative flex flex-col items-stretch gap-2 px-2.5 py-2 w-full rounded-[calc(var(--ui-radius)*2)] 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-(--ui-bg)/75 ring ring-(--ui-border)'
},
soft: {
root: 'bg-(--ui-bg-elevated)/50'
},
subtle: {
root: 'bg-(--ui-bg-elevated)/50 ring ring-(--ui-border)'
},
naked: {
root: ''
}
}
},
defaultVariants: {
variant: 'outline'
}
}
}
})
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-[calc(var(--ui-radius)*2)] 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-(--ui-bg)/75 ring ring-(--ui-border)'
},
soft: {
root: 'bg-(--ui-bg-elevated)/50'
},
subtle: {
root: 'bg-(--ui-bg-elevated)/50 ring ring-(--ui-border)'
},
naked: {
root: ''
}
}
},
defaultVariants: {
variant: 'outline'
}
}
}
})
]
})
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-[calc(var(--ui-radius)*2)] 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-(--ui-bg)/75 ring ring-(--ui-border)'
},
soft: {
root: 'bg-(--ui-bg-elevated)/50'
},
subtle: {
root: 'bg-(--ui-bg-elevated)/50 ring ring-(--ui-border)'
},
naked: {
root: ''
}
}
},
defaultVariants: {
variant: 'outline'
}
}
}
})
]
})