mbxai-chat-ui
v0.5.0
Published
A simple chat user interface built with Vue.js that simulates a conversation between a user and an assistant.
Downloads
2
Readme
MBXAI Chat UI
A simple chat user interface built with Vue.js that simulates a conversation between a user and an assistant.
Features
- Clean, modern UI design
- Real-time message display
- Multiple message types (text, image, file, code, math)
- File and image upload functionality
- Camera integration for taking photos
- LaTeX math formula rendering
- Code blocks with syntax highlighting and line numbers
- Copy functionality for all message types
- Automatic scrolling to new messages
- Suggested message chips for quick responses
- Confidential message masking with show/hide functionality for user inputs
- Automatic detection of sensitive information in user messages
- Loading state with spinner indicator and disabled send button
- Responsive design for both desktop and mobile
Project Setup
npm installStart Development Server
npm run devBuild for Production
npm run buildPreview Production Build
npm run previewUsing as an npm Dependency
You can use this chat UI as a dependency in your own Vue applications. Here's how:
Building the Library
Clone this repository:
git clone https://github.com/yourusername/mbxai-chat-ui.git cd mbxai-chat-uiInstall dependencies:
npm installBuild the library:
npm run build:lib
Publishing to npm (Optional)
If you want to publish the package to npm:
- Update the package name in
package.jsonif needed - Login to npm:
npm login - Publish the package:
npm publish
Installing in Your Project
npm install mbxai-chat-uiUsing the Components
Import the entire chat UI
<template>
<div class="app">
<h1>My Chat Application</h1>
<ChatUI
:initial-messages="initialMessages"
:suggestions="suggestions"
:confidential-words="confidentialWords"
:loading="isLoading"
@message-sent="handleMessage"
@suggestion-selected="handleSuggestion"
@new-message="handleNewMessage"
@history-updated="handleHistoryUpdate"
@file-uploaded="handleFileUpload"
@image-captured="handleImageCapture"
@math-sent="handleMathFormula"
ref="chatUI"
/>
</div>
</template>
<script setup>
import { ref } from 'vue';
import ChatUI from 'mbxai-chat-ui';
import 'mbxai-chat-ui/dist/mbxai-chat-ui.css';
const chatUI = ref(null);
const messageHistory = ref([]);
const isLoading = ref(false);
// Optional: Pre-populate the chat with initial messages
const initialMessages = ref([
{
id: 1,
type: 'text',
text: 'Welcome back! How can I assist you today?',
sender: {
id: 2,
name: 'Assistant'
},
timestamp: new Date()
}
]);
const suggestions = ref([
"What can you help me with?",
"Tell me about your features",
"How do I implement this?",
"$E = mc^2$" // LaTeX formula example
]);
// Define words that should trigger confidential masking
const confidentialWords = ref([
'password',
'token',
'secret',
'key',
'credential',
'username'
]);
const handleMessage = (message) => {
// Process the message when user sends it
console.log('Message sent:', message);
// Show loading indicator while processing
isLoading.value = true;
// Simulate AI response after 2 seconds
setTimeout(() => {
chatUI.value.addMessage({
type: 'text',
text: 'This is a response to your message: ' + message.text,
sender: {
id: 2,
name: 'Assistant'
}
});
// Hide loading indicator after response
isLoading.value = false;
}, 2000);
};
const handleNewMessage = (message) => {
// This is triggered for both user and assistant messages
console.log('New message added to chat:', message);
};
const handleHistoryUpdate = (history) => {
// Get the complete message history (including unmasked confidential messages)
messageHistory.value = history;
console.log('Full chat history:', history);
};
const handleSuggestion = (suggestion) => {
console.log('Suggestion selected:', suggestion);
};
const handleFileUpload = (fileMessage) => {
// Handle file uploads (documents, PDFs, etc.)
console.log('File uploaded:', fileMessage);
// Example: Process the file and respond
setTimeout(() => {
chatUI.value.addMessage({
type: 'text',
text: `I received your file: ${fileMessage.fileName}`,
sender: {
id: 2,
name: 'Assistant'
}
});
}, 1000);
};
const handleImageCapture = (imageMessage) => {
// Handle images from uploads or camera
console.log('Image received:', imageMessage);
// Example: Process the image and respond
setTimeout(() => {
chatUI.value.addMessage({
type: 'text',
text: 'I received your image and processed it',
sender: {
id: 2,
name: 'Assistant'
}
});
}, 1000);
};
const handleMathFormula = (mathMessage) => {
// Handle math formula messages
console.log('Math formula received:', mathMessage);
// Example: Respond with another formula
setTimeout(() => {
chatUI.value.addMathMessage('F = ma', {
id: 2,
name: 'Assistant'
});
}, 1000);
};
// You can also access the chat history directly
const getFullHistory = () => {
return chatUI.value.getMessageHistory();
};
// You can update the confidential words list dynamically
const updateConfidentialWords = (newWords) => {
chatUI.value.updateConfidentialWords(newWords);
};
// You can add different types of messages
const addTextMessage = (text) => {
chatUI.value.addMessage({
type: 'text',
text: text,
sender: {
id: 2,
name: 'Assistant'
}
});
};
const addImageMessage = (imageUrl, caption) => {
chatUI.value.addMessage({
type: 'image',
text: caption,
url: imageUrl,
sender: {
id: 2,
name: 'Assistant'
}
});
};
const addFileMessage = (fileUrl, fileName, fileSize) => {
chatUI.value.addMessage({
type: 'file',
text: 'Here is the requested file',
url: fileUrl,
fileName: fileName,
fileSize: fileSize,
sender: {
id: 2,
name: 'Assistant'
}
});
};
const addMathMessage = (formula) => {
chatUI.value.addMathMessage(formula, {
id: 2,
name: 'Assistant'
});
};
</script>Initial Messages
You can pre-populate the chat with initial messages using the initial-messages prop. This is useful for:
- Restoring a previous conversation
- Starting with a custom welcome message
- Pre-loading context or instructions
Basic Usage
<template>
<ChatUI :initial-messages="messages" />
</template>
<script setup>
import { ref } from 'vue';
import ChatUI from 'mbxai-chat-ui';
const messages = ref([
{
id: 1,
type: 'text',
text: 'Welcome back! I remember our previous conversation.',
sender: {
id: 2,
name: 'Assistant'
},
timestamp: new Date()
},
{
id: 2,
type: 'text',
text: 'Thanks! Can you remind me what we discussed?',
sender: {
id: 1,
name: 'You'
},
timestamp: new Date()
}
]);
</script>Dynamic Updates
The initial-messages prop is reactive, so you can update it to completely replace the chat history:
<script setup>
const messages = ref([]);
// Load a different conversation
const loadConversation = (conversationId) => {
// Replace all messages with new conversation
messages.value = getConversationHistory(conversationId);
};
// Clear chat and start fresh
const startNewChat = () => {
messages.value = [];
};
</script>Important Notes:
- When
initial-messagesis provided, it completely replaces the default welcome message - If you set
initial-messagesto an empty array, the default welcome message will be shown - Each message must have a unique
idand follow the message format specified below - Updating
initial-messageswill trigger thehistory-updatedevent
Import individual components
<template>
<div class="app">
<ChatWindow
:messages="messages"
:confidential-words="confidentialWords"
/>
<SuggestedMessages
:suggestions="suggestions"
@select-suggestion="handleSuggestion"
/>
<MessageInput
@send-message="handleMessage"
:confidential-mode="confidentialMode"
:loading="isLoading"
@toggle-confidential="toggleConfidential"
/>
</div>
</template>
<script setup>
import { ref } from 'vue';
import { ChatWindow, MessageInput, SuggestedMessages } from 'mbxai-chat-ui';
import 'mbxai-chat-ui/dist/mbxai-chat-ui.css';
// Your implementation...
</script>Message Format
Messages should follow this format:
{
id: Number, // Unique identifier
type: String, // 'text', 'math', 'code', 'image', or 'file'
text: String, // Message content, caption, math formula, or code
language: String, // For code messages, optional (e.g., 'javascript', 'python')
url: String, // For image or file messages
fileName: String, // For file messages
fileSize: Number, // For file messages, in bytes
sender: {
id: Number, // 1 for user, 2 for assistant (or any IDs you choose)
name: String, // Display name
avatar: String // Optional URL to avatar image
},
timestamp: Date, // Message timestamp
confidential: Boolean, // Whether this message contains sensitive information (only for user messages)
hasLatex: Boolean // Whether this text message contains LaTeX formulas
}Available Props
The ChatUI component accepts the following props:
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| initial-messages | Array | [] | Pre-populate the chat with initial messages. When empty, shows default welcome message. |
| suggestions | Array | [] | Array of suggestion strings to display as clickable chips below the chat. |
| confidential-words | Array | ['password', 'token', 'secret', 'key', 'credential'] | Words that trigger automatic confidential masking in user messages. |
| loading | Boolean | false | Show loading spinner and disable send button. Useful when processing AI responses. |
Available Events
The ChatUI component emits the following events:
| Event | Description | Payload |
|-------|-------------|---------|
| message-sent | Triggered when the user sends any message | Message object |
| suggestion-selected | Triggered when a suggestion is clicked | Suggestion text |
| new-message | Triggered when any message is added to the chat | Message object |
| history-updated | Triggered when the message history changes | Array of message objects |
| file-uploaded | Triggered when a file is uploaded | File message object |
| image-captured | Triggered when an image is uploaded or captured | Image message object |
| math-sent | Triggered when a math formula is sent | Math message object |
Loading State
The ChatUI component includes a loading state feature that shows a spinner and disables user input while processing:
Setting Loading State
- Set the
loadingprop totrueto enable loading mode - A spinning indicator appears under the last message
- The send button becomes disabled to prevent new messages
- Set the
Example Usage
<template> <ChatUI :loading="isLoading" @message-sent="handleMessage" /> </template> <script setup> import { ref } from 'vue'; const isLoading = ref(false); const handleMessage = async (message) => { // Show loading while processing isLoading.value = true; try { // Make API call to your backend/AI service const response = await fetch('/api/chat', { method: 'POST', body: JSON.stringify({ message: message.text }) }); const data = await response.json(); // Add AI response to chat chatUI.value.addMessage({ type: 'text', text: data.response, sender: { id: 2, name: 'Assistant' } }); } finally { // Always hide loading when done isLoading.value = false; } }; </script>Loading Behavior
- Loading spinner appears centered under the last message
- Send button becomes disabled and unclickable
- User cannot send new messages while loading is active
- Loading state persists until manually set to
false
Visual Design
- Clean 20px circular spinner with subtle animation
- Uses primary color (
#409eff) for the spinning border - Transparent background to not obstruct chat content
- Positioned to not interfere with chat flow
Message Types
The chat UI supports different types of messages:
Text Messages
- Standard text-based messages
- Can be marked as confidential for user messages
- Support for automatic sensitive information detection
- Support for inline LaTeX formulas using
$...$syntax - Support for display mode LaTeX formulas using
$$...$$syntax - Copy button to easily copy message text
Math Messages
- Dedicated type for mathematical formulas
- Rendered using KaTeX for beautiful math formatting
- Automatically detected when a message is wrapped in
$...$or$$...$$ - Can be created programmatically using
addMathMessage()
Code Messages
- Display code with syntax highlighting
- Support for line numbers
- Automatically detects the code language or can be specified
- Copy button for easy code copying
- Grey background for improved readability regardless of message type
Image Messages
- Display images inline with optional captions
- Support for uploading images from device
- Camera integration for capturing photos directly
- Click to open a full-screen preview
- Copy button to copy image captions
File Messages
- Display file information with name and size
- Download button for retrieving the file
- Copy button to copy file name
- Support for any file type
LaTeX Math Support
The chat UI includes support for mathematical formulas using LaTeX syntax:
Inline Formulas
- Wrap expressions in single dollar signs:
$E = mc^2$ - Rendered inline with the text
- Wrap expressions in single dollar signs:
Display Mode Formulas
- Wrap expressions in double dollar signs:
$$\int_{a}^{b} x^2 dx$$ - Rendered in display mode (centered, larger)
- Wrap expressions in double dollar signs:
Dedicated Math Messages
- When a message consists only of a LaTeX formula (wrapped in $ or $$), it's automatically converted to a dedicated math message type
- Math messages are optimized for formula display
Formula Detection
- The UI automatically detects LaTeX formulas in text messages
- You can check if a message contains LaTeX with the
hasLatexproperty
Programmatic Math Messages
- Create math messages programmatically:
chatUI.value.addMathMessage('E = mc^2', sender);
- Create math messages programmatically:
File and Image Upload
Users can upload files and images through:
File Upload Button
- Click the attachment icon to open options
- Select "Image" to upload an image file
- Select "File" to upload any other file type
- Add an optional caption before sending
Camera Capture
- Click the attachment icon and select "Camera"
- Take a photo using the device's camera
- Review the photo before sending
- Add an optional caption
Confidential Messages
The chat UI supports masking confidential messages that may contain sensitive information:
- User Messages Only: Confidential masking is only applied to messages from the user, not from the assistant
- Automatic Detection: User messages containing words like "password", "token", "secret", etc. are automatically masked
- Manual Toggle: Click the lock icon in the message input to manually mark the next user message as confidential
- Show/Hide Controls: Confidential messages include a "Show" button that reveals the actual content when clicked
- Customizable Keywords: Provide your own list of confidential words to detect via the
confidential-wordsprop - Unmasked Access: Parent applications can access the unmasked content through the history events or
getMessageHistory()method
This feature is useful for collecting sensitive information like passwords, account numbers, or personal details while ensuring that:
- Users can verify the content they've entered by clicking "Show"
- User messages with sensitive information are protected from shoulder surfing by default
- The parent application still has access to the unmasked content
- Assistant messages are always displayed in full, regardless of their content
Customization
You can customize the chat UI by:
- Modifying the styles in each component's
<style>section - Overriding CSS variables
- Extending components with your own implementation
- Providing custom confidential words for automatic detection
Technologies Used
- Vue.js 3
- Composition API with
<script setup> - KaTeX for LaTeX math rendering
- CSS custom properties for styling
Code Block Support
The chat UI includes support for code blocks with syntax highlighting:
Creating Code Messages
- Create a message with
type: 'code' - Provide the code in the
textproperty - Optionally specify the language in the
languageproperty
- Create a message with
Syntax Highlighting
- Code is automatically highlighted based on the specified language
- If no language is specified, automatic language detection is attempted
- Powered by highlight.js with support for most programming languages
Line Numbers
- Code blocks display line numbers for better readability
- Numbers are properly aligned with code lines
Copy Functionality
- Each code block includes a copy button
- Click to copy the entire code snippet to clipboard
- Visual feedback when code is copied
Example Usage
chatUI.value.addMessage({ type: 'code', text: 'function hello() {\n console.log("Hello world!");\n}', language: 'javascript', sender: { id: 2, name: 'Assistant' }, timestamp: new Date() });
Copy Functionality
Each message type includes a convenient copy button:
Text Messages
- Copy button appears on hover
- Copies the entire message text to clipboard
Code Messages
- Copy button for the entire code block
- Positioned in the top-right corner of the code block
Image Messages
- Copy button for the image caption
- Appears on hover over the image container
File Messages
- Copy button for the file name
- Positioned next to the download button
Visual Feedback
- "Copied!" tooltip appears when content is copied
- Subtle animations provide user feedback
