@fengxie/vue-im
v0.2.2
Published
A beautiful and modern Vue 3 IM (Instant Messaging) UI library built with Tailwind CSS.
Downloads
496
Readme
@fengxie/vue-im
A beautiful and modern Vue 3 IM (Instant Messaging) UI library built with Tailwind CSS.
This library provides a set of highly customizable, responsive, and ready-to-use chat components for building messaging web applications in Vue 3.
Features
- 💅 Modern Design: Premium UI with glassmorphism, responsive layouts, and Tailwind CSS.
- 🧩 Modular Components: Includes
IMLayout,Sidebar,ChatArea, andRightPanel. - 🌐 i18n Support: Auto-translation UI toggles and layout considerations for multi-language.
- 📦 TypeScript: Fully typed props and events for seamless developer experience.
Installation
You can install the library via npm, pnpm, or yarn:
npm install @fengxie/vue-im
# or
pnpm install @fengxie/vue-im
# or
yarn add @fengxie/vue-imPeer Dependencies
Make sure you have vue and tailwindcss installed in your project:
npm install vue tailwindcssYou must also import vue-im's styles, or simply let Tailwind CSS scan your node_modules. If you use Tailwind CSS v4, make sure to add vue-im to your content paths or ignore if not required by v4's new auto-scanning, but if you need the direct css:
In your main.ts or App.vue:
import '@fengxie/vue-im/dist/style.css';Quick Start / Usage
Here is a complete example of how to build a full IM layout using @fengxie/vue-im:
<script setup lang="ts">
import { ref } from 'vue';
import { IMLayout, Sidebar, ChatArea, RightPanel } from '@fengxie/vue-im';
import type { Account, Contact, Message, AppLanguage } from '@fengxie/vue-im';
// ---- State ----
const accounts = ref<Account[]>([/* your accounts */]);
const contacts = ref<Contact[]>([/* your contacts */]);
const activeAccount = ref<Account>(accounts.value[0]);
const activeContact = ref<Contact>(contacts.value[0]);
const messages = ref<Message[]>([]);
const lang = ref<AppLanguage>('zh');
const aiAutoReply = ref(false);
const autoTranslateReceive = ref(false);
const autoTranslateSend = ref(false);
const searchQuery = ref('');
const activeFilter = ref('all');
// Pagination state
const hasMore = ref(true);
const isLoadingMore = ref(false);
// ---- Sidebar Events ----
const handleContactSelect = (contact: Contact) => {
activeContact.value = contact;
// Fetch messages for this contact from API...
};
// ---- ChatArea Events ----
const handleSendMessage = (payload: { text: string; replyTo?: Message }) => {
const newMsg: Message = {
id: Date.now().toString(),
senderId: 'me',
text: payload.text,
timestamp: new Date().toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' }),
type: 'text'
};
messages.value = [...messages.value, newMsg];
// Call your API to persist the message...
};
const handleRecallMessage = (id: string) => {
messages.value = messages.value.filter(m => m.id !== id);
// Call your API to recall...
};
const handleUploadImage = (file: File) => {
// Upload the file via your API...
};
const handleUploadFile = (file: File) => {
// Upload the file via your API...
};
const handleLoadMore = () => {
isLoadingMore.value = true;
// Fetch older messages from your API, then prepend:
// messages.value = [...olderMessages, ...messages.value];
// hasMore.value = response.hasMore;
// isLoadingMore.value = false;
};
// ---- RightPanel Events ----
const handleSendOrderCard = (order: any) => { /* send order card */ };
const handleActionClick = (action: string) => { /* handle biz action */ };
const handleSendProductMedia = (product: any) => { /* handle product send */ };
</script>
<template>
<IMLayout>
<template #sidebar>
<Sidebar
:accounts="accounts"
:activeAccount="activeAccount"
:contacts="contacts"
:activeContact="activeContact"
v-model:searchQuery="searchQuery"
v-model:activeFilter="activeFilter"
@accountSelect="acc => activeAccount = acc"
@contactSelect="handleContactSelect"
/>
</template>
<template #chatArea>
<ChatArea
:contact="activeContact"
:messages="messages"
:hasMore="hasMore"
:isLoadingMore="isLoadingMore"
v-model:aiAutoReply="aiAutoReply"
v-model:autoTranslateReceive="autoTranslateReceive"
v-model:autoTranslateSend="autoTranslateSend"
v-model:lang="lang"
@loadMore="handleLoadMore"
@sendMessage="handleSendMessage"
@recallMessage="handleRecallMessage"
@uploadImage="handleUploadImage"
@uploadFile="handleUploadFile"
/>
</template>
<template #rightPanel>
<RightPanel
:lang="lang"
:contact="activeContact"
:orderInfo="yourOrderData"
:products="yourProductsList"
@sendOrderCard="handleSendOrderCard"
@actionClick="handleActionClick"
@sendProductMedia="handleSendProductMedia"
/>
</template>
</IMLayout>
</template>Available Components
IMLayout
The base wrapper component that provides the CSS Grid layout for the traditional IM interface. Provides three named slots: #sidebar, #chatArea, #rightPanel.
Sidebar
Displays the active user account, search bar, and the contacts list.
- Props:
accounts: List of available user accounts.activeAccount: Currently selected account.contacts: Array of contacts.activeContact: The currently selected contact for chat.searchQuery(v-model): Search input text.activeFilter(v-model): Active contact filter tab.
- Events:
@accountSelect(account)@contactSelect(contact)@update:searchQuery(query)@update:activeFilter(filter)
ChatArea
The main message window where the conversation happens. Includes built-in support for reverse infinite scrolling (loading historical messages).
- Props:
contact: The current activeContact.messages: An array ofMessageobjects to render.aiAutoReply,autoTranslateReceive,autoTranslateSend: Control various chat functionalities.lang: Current language interface toggle (supportszh,en, etc.).hasMore(optional): Boolean indicating if there are more historical messages to load.isLoadingMore(optional): Boolean indicating if historical messages are currently being fetched.
- Events:
@loadMore: Emitted when the user scrolls to the top of the chat area.@sendMessage({ text, replyTo }): Emitted when the user sends a message.@recallMessage(id): Emitted when a message is recalled.@uploadImage(file)&@uploadFile(file): Emitted on file selection.
RightPanel
Extra pane for contact details, quick actions, and order/product information context.
- Props:
contact: The currently activeContact.orderInfo: Object containing contextual order information.products: Object for recommended products list.
- Events:
@sendOrderCard(orderInfo)@actionClick(actionType): Emitted with string 'contract', 'payment', 'logistics', 'coupon'.@sendProductMedia(product)
Publishing Workflow (For Maintainers)
If you are a maintainer of this library, here is the complete flow to publish updates to NPM:
- Build the Library
Run the build script to generate the
/distartifacts (ES and UMD formats, plus Type Definitions).pnpm run build - Login to NPM
If you aren't already authenticated on your machine, log in.
npm login # You will be prompted for your username, password, and OTP. - Publish
Once logged in and built, publish the package.
(Make sure you have incremented the
versioninpackage.jsonfor subsequent updates)
(Note: you can usenpm publish --access publicnpm publish --dry-runto preview what files will be included before actually publishing)
