Vue Beautiful Chat

2.5.0 · active · verified Sun Apr 19

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

Warnings

Install

Imports

Quickstart

This example demonstrates how to integrate `vue-beautiful-chat` into a Vue application, showcasing component registration, prop configuration, event handling for messages and typing, and basic chat window management including opening/closing and sending/receiving messages.

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>

view raw JSON →