@blumessage/react-chat
v1.10.0
Published
A React TypeScript chat widget component with floating button, theming, and Blumessage API integration
Downloads
118
Maintainers
Readme
Blumessage React Chat Component
A React TypeScript chat widget component with floating button, theming, and Blumessage API integration. Features real-time messaging, conversation persistence, error handling, and a modern UI built with Tailwind CSS.
✨ Features
- 🎈 Floating Chat Widget - Appears as a button, expands to full chat
- 🎨 Light/Dark Themes - Built-in theme support
- 💾 Persistent Storage - Save conversations to localStorage or sessionStorage
- 🔄 Real-time Messaging - Instant API integration with Blumessage
- 📱 Responsive Design - Works on desktop and mobile
- 🎯 Flexible Icons - Supports various icon patterns
- ⚡ Error Handling - Comprehensive error callbacks
- 🔧 Highly Customizable - Extensive prop options
Installation
NPM Package (Recommended)
npm i @blumessage/react-chatBrowser Versions
Option 1: Standalone (Includes React)
For the simplest setup with everything included:
<!-- Load the Blumessage Chat component (includes React) -->
<script src="path/to/index.js"></script>Option 2: External React (Smaller Bundle)
For when you already have React loaded:
<!-- Load React and ReactDOM from CDN -->
<script crossorigin src="https://unpkg.com/react@18/umd/react.production.min.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@18/umd/react-dom.production.min.js"></script>
<!-- Load the Blumessage Chat component -->
<script src="path/to/blumessage-chat.browser.js"></script>See BROWSER_USAGE.md for complete browser usage documentation.
Quick Start
Floating Chat Widget (Default)
import React from 'react';
import { BlumessageChat } from '@blumessage/react-chat';
function App() {
return (
<BlumessageChat
apiKey="your-blumessage-api-key"
/>
);
}Embedded Chat
import React from 'react';
import { BlumessageChat } from '@blumessage/react-chat';
function App() {
return (
<BlumessageChat
apiKey="your-blumessage-api-key"
floating={false}
width="400px"
height="600px"
/>
);
}Complete Props Reference
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| Required |
| apiKey | string | - | Your Blumessage API key |
| Display & Content |
| name | string | "Blumessage AI" | Display name for the AI assistant |
| subtitle | string | "Online • Instant responses" | Subtitle shown under the name |
| placeholder | string | "Type your message..." | Input placeholder text |
| theme | 'light' \| 'dark' | 'light' | Chat widget theme |
| primaryColor | string | "linear-gradient(to right, #3b82f6,rgb(8, 98, 242))" | Primary color/gradient |
| Layout & Sizing |
| floating | boolean | true | Show as floating widget vs embedded |
| width | string | '380px' (medium) | Custom width (overrides size) |
| height | string | '500px' (medium) | Custom height (overrides size) |
| size | 'small' \| 'medium' \| 'large' | 'medium' | Predefined size preset |
| fullScreen | boolean | false | Force full screen mode |
| Floating Widget Options |
| buttonText | string | "Chat with us" | Text on floating button |
| buttonPosition | 'bottom-right' \| 'bottom-left' \| 'top-right' \| 'top-left' | 'bottom-right' | Button position |
| buttonStyle | React.CSSProperties | - | Custom button styles |
| defaultOpen | boolean | false | Start with chat open |
| maximizeToggleButton | boolean | true | Show maximize/minimize button |
| icon | string | 'message-circle' | Icon for button (flexible naming) |
| Help Bubble Options |
| showHelpBubble | boolean | true | Show help bubble above floating button |
| helpBubbleMessage | string | "👋 If you need help chat with us" | Message text in help bubble |
| helpBubbleIcon | string | 'hand' | Icon for help bubble (supports lucide-react icon names) |
| helpBubbleShowAfter | number | 1 | Seconds to wait before showing bubble |
| helpBubbleHideAfter | number | 5 | Seconds to wait before hiding bubble (0 = never hide) |
| Messages & Data |
| initialMessages | Message[] | [] | Pre-populate with messages |
| conversationId | string | - | Continue specific conversation |
| persistent | boolean | false | Use localStorage vs sessionStorage |
| showTimestamps | boolean | false | Display timestamps: today="2:00 PM", older="17 July, 1:00 PM" |
| typingText | string | "Agent is typing..." | Custom text shown while waiting for assistant response |
| animatedTypingIndicator | boolean | false | Replace typing text with a premium animated pulsing dots indicator |
| emptyStateText | string | "Start a conversation!" | Text shown when no messages are present |
| markdown | boolean | true | Enable markdown rendering for messages |
| disableAutoScroll | boolean | false | Disable automatic scrolling to bottom when new messages arrive |
| context | Record<string, any> | - | Arbitrary user context data (name, email, etc.) passed to the AI agent for personalized responses |
| Event Callbacks |
| onUserMessage | (message: Message) => void | - | Called when user sends message |
| onAssistantMessage | (message: Message) => void | - | Called when assistant responds |
| onConversationIdChange | (id: string \| null) => void | - | Called when conversation ID changes |
| onChatWidgetOpen | () => void | - | Called when floating chat opens |
| onChatWidgetClosed | () => void | - | Called when floating chat closes |
| onError | (error: string, context?: string) => void | - | Called on any error |
Advanced Usage Examples
Providing User Context
Pass user data to help the AI agent personalize responses:
<BlumessageChat
apiKey="your-api-key"
context={{
name: "John Doe",
email: "[email protected]",
plan: "premium",
userId: 12345,
tags: ["vip", "early-adopter"],
}}
/>The context prop accepts any key-value pairs (Record<string, any>). Values can be strings, numbers, booleans, arrays, or objects. The context is sent with every message and merged on the server, so you can update it dynamically across the conversation.
Dark Theme with Callbacks
<BlumessageChat
apiKey="your-api-key"
theme="dark"
name="Support Bot"
onUserMessage={(message) => console.log('User:', message.content)}
onAssistantMessage={(message) => console.log('Bot:', message.content)}
onError={(error, context) => console.error(`Error in ${context}:`, error)}
/>Persistent Storage
<BlumessageChat
apiKey="your-api-key"
persistent={true} // Saves to localStorage instead of sessionStorage
onConversationIdChange={(id) => {
// Optionally save ID to your own storage
if (id) localStorage.setItem('my-chat-id', id);
}}
/>Custom Styling & Size
<BlumessageChat
apiKey="your-api-key"
size="large"
primaryColor="linear-gradient(45deg, #ff6b6b, #4ecdc4)"
buttonPosition="bottom-left"
buttonText="Need Help?"
icon="headphones"
maximizeToggleButton={true}
/>Embedded with Initial Messages
const initialMessages = [
{
id: '1',
role: 'assistant' as const,
content: 'Hello! How can I help you today?',
timestamp: Date.now()
}
];
<BlumessageChat
apiKey="your-api-key"
floating={false}
width="100%"
height="500px"
initialMessages={initialMessages}
placeholder="Ask me anything..."
/>Help Bubble Configuration
<BlumessageChat
apiKey="your-api-key"
floating={true}
showHelpBubble={true}
helpBubbleMessage="👋 Need assistance? We're here to help!"
helpBubbleIcon="hand" // Use hand icon (default)
helpBubbleShowAfter={3} // Show after 3 seconds
helpBubbleHideAfter={10} // Hide after 10 seconds
/>Custom Help Bubble Icons
<BlumessageChat
apiKey="your-api-key"
floating={true}
showHelpBubble={true}
helpBubbleIcon="star" // Use star icon
helpBubbleMessage="⭐ Rate our service!"
helpBubbleShowAfter={2}
helpBubbleHideAfter={8}
/>
<BlumessageChat
apiKey="your-api-key"
floating={true}
showHelpBubble={true}
helpBubbleIcon="lightbulb" // Use lightbulb icon
helpBubbleMessage="💡 Got an idea? Let's discuss it!"
helpBubbleShowAfter={1}
helpBubbleHideAfter={0} // Never hide
/>
<BlumessageChat
apiKey="your-api-key"
floating={true}
showHelpBubble={true}
helpBubbleIcon="help-circle" // Use help icon
helpBubbleMessage="❓ Questions? We're here to help!"
helpBubbleShowAfter={5}
helpBubbleHideAfter={15}
/>
### Persistent Help Bubble (Never Hide)
```tsx
<BlumessageChat
apiKey="your-api-key"
floating={true}
showHelpBubble={true}
helpBubbleMessage="💬 Questions? Click to chat with us!"
helpBubbleShowAfter={2} // Show after 2 seconds
helpBubbleHideAfter={0} // Never hide (0 = persistent)
/>Chat with Timestamps
<BlumessageChat
apiKey="your-api-key"
showTimestamps={true} // Shows "2:00 PM" or "17 July, 1:00 PM"
floating={false}
initialMessages={[
{
id: '1',
role: 'assistant' as const,
content: 'Message from today',
timestamp: Date.now() - (60 * 60 * 1000) // Shows: "2:00 PM" (or "14:00")
},
{
id: '2',
role: 'user' as const,
content: 'Message from yesterday',
timestamp: Date.now() - (24 * 60 * 60 * 1000) // Shows: "17 July, 1:00 PM"
}
]}
/>Custom Typing Indicator
<BlumessageChat
apiKey="your-api-key"
typingText="Support agent is typing..." // Custom loading message
// Or use different text for different languages:
// typingText="L'agent écrit..." // French
// typingText="El agente está escribiendo..." // Spanish
/>Animated Typing Indicator
<BlumessageChat
apiKey="your-api-key"
animatedTypingIndicator={true} // Pulsing dots animation instead of text
/>Custom Empty State Text
<BlumessageChat
apiKey="your-api-key"
emptyStateText="Welcome! How can I help you today?" // Custom empty state message
// Or use different text for different contexts:
// emptyStateText="Ask me anything about our products..."
// emptyStateText="Ready to assist with your questions!"
/>Disable Auto-Scroll
<BlumessageChat
apiKey="your-api-key"
disableAutoScroll={true} // Prevents automatic scrolling to bottom
// Useful when you want users to maintain their scroll position
// or when implementing custom scroll behavior
/>Icon Options
The icon prop accepts any lucide-react icon name with flexible naming patterns. The component intelligently matches your input to the appropriate lucide-react icon:
// ✅ Any lucide-react icon works:
icon="message-circle" // MessageCircle
icon="phone" // Phone
icon="mail" // Mail
icon="headphones" // Headphones
icon="bot" // Bot
icon="users" // Users
icon="heart" // Heart
icon="star" // Star
icon="zap" // Zap
icon="settings" // Settings
icon="help-circle" // HelpCircle
icon="info" // Info
icon="alert-triangle" // AlertTriangle
// ✅ Flexible naming patterns (case-insensitive, ignores hyphens/underscores):
icon="MessageCircle" // → MessageCircle
icon="message_circle" // → MessageCircle
icon="message circle" // → MessageCircle
icon="chat" // → MessageCircle (smart matching)
icon="messaging" // → MessageCircle (smart matching)
icon="support" // → Headphones (smart matching)
icon="email" // → Mail (smart matching)
icon="call" // → Phone (smart matching)
// ✅ Default fallback: MessageCircle (if no match found)
icon="unknown-icon" // → MessageCircleBrowse all available icons at: lucide.dev/icons
Simply use the icon name from lucide-react, and the component will handle the rest!
Error Handling
The onError callback provides detailed error context:
<BlumessageChat
apiKey="your-api-key"
onError={(error, context) => {
switch(context) {
case 'missing_api_key':
// Handle missing API key
break;
case 'api_key_validation':
// Handle invalid API key
break;
case 'network_error':
// Handle network issues
break;
case 'conversation_history':
// Handle history fetch errors
break;
case 'message_send':
// Handle message sending errors
break;
}
}}
/>External Message Submission
The component supports external message submission through a ref, allowing parent components to programmatically send messages and control the chat widget.
Using the Ref
import React, { useRef } from 'react';
import { BlumessageChat, BlumessageChatRef } from '@blumessage/react-chat';
function App() {
const chatRef = useRef<BlumessageChatRef>(null);
const sendExternalMessage = async () => {
if (chatRef.current) {
await chatRef.current.sendMessage("Hello from external component!");
}
};
const openChat = () => {
chatRef.current?.openChat();
};
const closeChat = () => {
chatRef.current?.closeChat();
};
const clearChat = () => {
chatRef.current?.clearConversation();
};
const getMessages = () => {
const messages = chatRef.current?.getMessages();
console.log('Current messages:', messages);
};
const getToken = () => {
const token = chatRef.current?.getToken();
console.log('Current conversation token:', token);
};
return (
<div>
<button onClick={sendExternalMessage}>Send External Message</button>
<button onClick={openChat}>Open Chat</button>
<button onClick={closeChat}>Close Chat</button>
<button onClick={clearChat}>Clear Chat</button>
<button onClick={getMessages}>Get Messages</button>
<button onClick={getToken}>Get Token</button>
<BlumessageChat
ref={chatRef}
apiKey="your-api-key"
floating={true}
/>
</div>
);
}Available Ref Methods
| Method | Type | Description |
|--------|------|-------------|
| sendMessage(message: string) | Promise<void> | Send a message programmatically |
| openChat() | void | Open the floating chat widget |
| closeChat() | void | Close the floating chat widget |
| clearConversation() | void | Clear all messages and reset conversation |
| getMessages() | Message[] | Get current messages array |
| getToken() | string \| null | Get current conversation token |
Complete Example with External Controls
import React, { useRef, useState } from 'react';
import { BlumessageChat, BlumessageChatRef } from '@blumessage/react-chat';
function App() {
const [externalMessage, setExternalMessage] = useState('');
const chatRef = useRef<BlumessageChatRef>(null);
const handleSendExternalMessage = async () => {
if (!externalMessage.trim() || !chatRef.current) return;
try {
await chatRef.current.sendMessage(externalMessage);
setExternalMessage('');
console.log('External message sent successfully');
} catch (error) {
console.error('Failed to send external message:', error);
}
};
return (
<div>
<div style={{ marginBottom: '20px' }}>
<input
type="text"
value={externalMessage}
onChange={(e) => setExternalMessage(e.target.value)}
placeholder="Type a message to send externally..."
onKeyPress={(e) => e.key === 'Enter' && handleSendExternalMessage()}
/>
<button onClick={handleSendExternalMessage}>Send</button>
<button onClick={() => chatRef.current?.openChat()}>Open Chat</button>
<button onClick={() => chatRef.current?.closeChat()}>Close Chat</button>
<button onClick={() => chatRef.current?.clearConversation()}>Clear Chat</button>
</div>
<BlumessageChat
ref={chatRef}
apiKey="your-api-key"
floating={true}
onUserMessage={(message) => console.log('User message:', message)}
onAssistantMessage={(message) => console.log('Assistant message:', message)}
/>
</div>
);
}TypeScript Support
Full TypeScript definitions included:
import { BlumessageChat, Message, BlumessageChatProps, BlumessageChatRef } from '@blumessage/react-chat';
interface Message {
id: string;
role: 'user' | 'assistant';
content: string;
timestamp: number;
}
interface BlumessageChatRef {
sendMessage: (message: string) => Promise<void>;
openChat: () => void;
closeChat: () => void;
clearConversation: () => void;
getMessages: () => Message[];
getToken: () => string | null;
}Storage Behavior
- SessionStorage (default): Conversations persist until browser tab closes
- LocalStorage (persistent=true): Conversations persist across browser sessions
- Automatic cleanup: Invalid conversation IDs are automatically cleared
- History restoration: Previous conversations load automatically on component mount
Browser Support
- Modern browsers with ES2017+ support
- React 18+
- TypeScript 4.5+
Building
Standard Build (ES Modules)
npm run buildBrowser Versions
Standalone (Includes React)
npm run build:commonjsThis creates dist/index.js which includes React and can be used directly in browsers.
External React (Smaller Bundle)
npm run build:browserThis creates dist/blumessage-chat.browser.js which requires React to be loaded separately.
License
UNLICENSED - For use only by customers with an active Blumessage subscription.
Support
For feature requests, technical support and assistance, please contact us at: [email protected]
