Chat Input
A Telegram-style chat bottom bar with auto-resizing textarea, action panel, send button, and optional attach/emoji/voice actions.
Basic
Type a message and press Enter to send (Shift+Enter for newline). Click the paperclip to open the actions panel.
<script setup>
import { ref } from 'vue'
const msg = ref('')
</script>
<VxChatInput v-model="msg" @send="handleSend" />Actions Panel
Click the paperclip icon to reveal the Telegram-style actions panel. The icon rotates 45deg when active. Default actions: Photo, File, Location, Contact, Poll.
<script setup>
function onAction(key, item) {
console.log('Action:', key, item)
}
</script>
<VxChatInput @action="onAction" />Custom Actions
Pass your own action items array.
<VxChatInput
:actions="[
{ key: 'camera', label: 'Camera', color: '#E91E63' },
{ key: 'gif', label: 'GIF', color: '#FF9800' },
{ key: 'sticker', label: 'Sticker', color: '#9C27B0' },
]"
@action="onAction"
/>Disable Actions Panel
Pass :actions="false" to make the paperclip button emit attach instead of opening the panel.
<VxChatInput :actions="false" @attach="openFilePicker" />Variants
Three visual styles: default, outline, and ghost.
<VxChatInput variant="default" />
<VxChatInput variant="outline" />
<VxChatInput variant="ghost" />Voice Button
Show a mic button when the input is empty with show-voice. The mic morphs into send with a rotate animation when text is typed.
<VxChatInput show-voice @voice="startRecording" />Reply Preview
Pass a reply-to object to show a reply preview above the input. Slides in/out with animation.
<script setup>
import { ref } from 'vue'
const replyTo = ref({ name: 'Alice', content: 'Hey, did you finish the design?' })
</script>
<VxChatInput
:reply-to="replyTo"
@cancel-reply="replyTo = null"
/>Disabled
<VxChatInput disabled />Custom Actions (Slots)
Use prepend and append slots to replace the default action buttons entirely.
<VxChatInput>
<template #prepend>
<button @click="openCamera">📷</button>
</template>
<template #append>
<button @click="openGif">GIF</button>
</template>
</VxChatInput>API
Props
| Prop | Type | Default | Description |
|---|---|---|---|
model-value | string | '' | v-model text value |
placeholder | string | 'Type a message...' | Placeholder text |
variant | 'default' | 'outline' | 'ghost' | 'default' | Visual style |
disabled | boolean | false | Disable input |
show-attach | boolean | true | Show attach/actions button |
show-emoji | boolean | true | Show emoji button |
show-voice | boolean | false | Show voice/mic button (when input is empty) |
max-rows | number | 5 | Max auto-grow rows |
reply-to | { name?: string; content?: string } | null | null | Reply preview |
actions | ChatInputAction[] | false | default 5 items | Action panel items. Pass false to disable panel |
Events
| Event | Payload | Description |
|---|---|---|
update:modelValue | string | v-model update |
send | string | Emitted on Enter or send button click (trimmed text) |
attach | — | Attach button clicked (only when actions is false) |
emoji | — | Emoji button clicked |
voice | — | Voice button clicked |
cancel-reply | — | Reply close button clicked |
action | key, item | Action panel item clicked |
Slots
| Slot | Description |
|---|---|
prepend | Replace left action buttons (default: attach) |
append | Replace right action buttons (default: emoji) |
Exposed
| Method | Description |
|---|---|
focus() | Focus the textarea programmatically |
ChatInputAction
interface ChatInputAction {
key: string // Unique action key
label: string // Display label
icon?: string // Custom icon (optional)
color?: string // Circle background color
}