Vue Beautiful Chat
Vue Beautiful Chat is an open-source, backend-agnostic chat user interface component designed for Vue.js applications. Currently stable at version 2.5.0, it offers an intercom-like chat window that is highly customizable and free to use. Key features include group chat capabilities, a togglable user list with profiles, automatic URL linking in messages, and support for message styling via `msgdown`. The component focuses solely on the presentation layer, requiring developers to implement their own messaging backend. It distinguishes itself by providing a rich set of UI features out-of-the-box and maintains a steady release cadence for new features and improvements.
Common errors
-
[Vue warn]: Unknown custom element: <beautiful-chat> - did you register the component correctly?
cause The `vue-beautiful-chat` plugin was not registered with your Vue application.fixEnsure you call `app.use(Chat)` (for Vue 3) or `Vue.use(Chat)` (for Vue 2) in your application's entry file before mounting your Vue app. -
Module not found: Error: Can't resolve 'vue-beautiful-chat/src/assets/close-icon.png'
cause Your build tool (e.g., Webpack, Vite) is unable to resolve or process the image file imported directly from the `src` directory within the `node_modules` package.fixCheck your bundler configuration for asset handling. If the issue persists, consider downloading the necessary icon files and importing them from your local project's asset directory instead of directly from the package's `src` folder.
Warnings
- breaking The 2.0.0 release introduced significant API changes, including new features like group chat, user lists, user profiles, and message autolink, which altered the prop and event interfaces of the component.
- gotcha The library is backend-agnostic, meaning it only provides the user interface component. You must implement your own real-time messaging backend and integration logic to handle message persistence, delivery, and user management.
- gotcha The examples and quickstart import image assets directly from `vue-beautiful-chat/src/assets/`. While this works in development, relying on `src` paths in `node_modules` can be brittle and may break in production builds or with different bundler configurations.
Install
-
npm install vue-beautiful-chat -
yarn add vue-beautiful-chat -
pnpm add vue-beautiful-chat
Imports
- Chat
import { Chat } from 'vue-beautiful-chat'import Chat from 'vue-beautiful-chat'
- BeautifulChat
import BeautifulChat from 'vue-beautiful-chat/dist/BeautifulChat.vue'
Vue.use(Chat) // component <beautiful-chat> is registered globally
- Icons (e.g., CloseIcon)
import CloseIcon from 'vue-beautiful-chat/assets/close-icon.png'
import CloseIcon from 'vue-beautiful-chat/src/assets/close-icon.png'
Quickstart
import { createApp } from 'vue';
import App from './App.vue';
import Chat from 'vue-beautiful-chat';
// Import example icons (note: these paths can be brittle, see warnings)
import CloseIcon from 'vue-beautiful-chat/src/assets/close-icon.png';
import OpenIcon from 'vue-beautiful-chat/src/assets/logo-no-bg.svg';
import FileIcon from 'vue-beautiful-chat/src/assets/file.svg';
import CloseIconSvg from 'vue-beautiful-chat/src/assets/close.svg';
// main.js (or equivalent Vue entry file)
const app = createApp(App);
app.use(Chat); // Registers the <beautiful-chat> component globally
app.mount('#app');
// App.vue (example component)
<template>
<div id="app">
<beautiful-chat
:participants="participants"
:titleImageUrl="titleImageUrl"
:onMessageWasSent="onMessageWasSent"
:messageList="messageList"
:newMessagesCount="newMessagesCount"
:isOpen="isChatOpen"
:close="closeChat"
:icons="icons"
:open="openChat"
:showEmoji="true"
:showFile="true"
:showEdition="true"
:showDeletion="true"
:showTypingIndicator="showTypingIndicator"
:showLauncher="true"
:showCloseButton="true"
:colors="colors"
:alwaysScrollToBottom="alwaysScrollToBottom"
:messageStyling="messageStyling"
@onType="handleOnType"
@edit="editMessage" />
</div>
</template>
<script>
export default {
name: 'App',
data() {
return {
icons:{
open:{ img: OpenIcon, name: 'default' },
close:{ img: CloseIcon, name: 'default' },
file:{ img: FileIcon, name: 'default' },
closeSvg:{ img: CloseIconSvg, name: 'default' },
},
participants: [
{ id: 'user1', name: 'Matteo', imageUrl: 'https://avatars3.githubusercontent.com/u/1915989?s=230&v=4' },
{ id: 'user2', name: 'Support', imageUrl: 'https://avatars3.githubusercontent.com/u/37018832?s=200&v=4' }
],
titleImageUrl: 'https://a.slack-edge.com/66f9/img/avatars-teams/ava_0001-34.png',
messageList: [
{ type: 'text', author: `me`, data: { text: `Hello from Vue Beautiful Chat!` } },
{ type: 'text', author: `user1`, data: { text: `How can I assist you today?` } }
],
newMessagesCount: 0,
isChatOpen: false,
showTypingIndicator: '',
colors: {
header: { bg: '#4e8cff', text: '#ffffff' },
launcher: { bg: '#4e8cff' },
messageList: { bg: '#ffffff' },
sentMessage: { bg: '#4e8cff', text: '#ffffff' },
receivedMessage: { bg: '#eaeaea', text: '#000000' } // Completed value
},
alwaysScrollToBottom: true,
messageStyling: true,
};
},
methods: {
onMessageWasSent(message) {
this.messageList.push(message);
// Simulate an AI or another user's response after a short delay
setTimeout(() => {
const responseMessage = {
type: 'text',
author: 'user2',
data: { text: `I received your message: "${message.data.text}"` }
};
this.messageList.push(responseMessage);
this.newMessagesCount++;
}, 1000);
},
handleOnType(event) {
console.log('User is typing:', event.input, event.from);
// Implement logic to show typing indicator for specific users
// e.g., this.showTypingIndicator = event.from;
},
editMessage(message) {
const index = this.messageList.findIndex(m => m.id === message.id);
if (index !== -1) {
this.messageList.splice(index, 1, message);
}
console.log('Message edited:', message);
},
closeChat() {
this.isChatOpen = false;
},
openChat() {
this.isChatOpen = true;
this.newMessagesCount = 0; // Reset count when chat is opened
}
},
mounted() {
// Open chat window automatically after a short delay for demo
setTimeout(() => {
this.isChatOpen = true;
}, 500);
}
};
</script>
<style>
#app {
font-family: Avenir, Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
margin-top: 60px;
}
</style>