@mypatientspace/chatbot-widget
v1.0.78
Published
Embeddable healthcare chatbot widget for websites and mobile apps
Maintainers
Readme
MPS Chatbot Widget
A standalone chatbot widget that third-party websites can embed via a single <script> tag.
Features
- Self-contained React application bundled into a single JS file
- Easy integration with any website
- Embedded mode (default) or floating button mode
- Customizable theming with light, dark, and system color modes
- Style isolation (won't conflict with host site CSS)
- Native mobile support via WebView
- Voice input support
- Quick action buttons
- Survey/questionnaire support
- Content citations with overlay view
Tech Stack
- React 19 with TypeScript
- Vite (library mode build)
- Emotion (CSS-in-JS for style isolation)
- lucide-react (icons)
Compatibility
Via CDN/Script Tag (Any Project)
When using the UMD bundle via <script> tag, the widget bundles its own React and renders in an isolated container. Your project's React version doesn't matter — this works with any framework (or no framework at all), including:
- Vanilla JavaScript/HTML
- jQuery
- Angular, Vue, Svelte
- Older React versions (14, 15, 16, etc.)
Via npm Import (React 18+ Required)
When importing as an ES module in a React project:
import '@mypatientspace/chatbot-widget';You need React 18 or higher. The widget uses modern React features (hooks, Context API) that aren't available in older versions.
| Integration Method | React Version Required | |--------------------|------------------------| | CDN / Script tag | Any (bundles own React) | | npm import | React 18+ |
Installation
Via CDN (Recommended)
unpkg:
<script src="https://unpkg.com/@mypatientspace/chatbot-widget@latest/dist/mypatientspace-widget.umd.js"></script>jsDelivr:
<script src="https://cdn.jsdelivr.net/npm/@mypatientspace/chatbot-widget@latest/dist/mypatientspace-widget.umd.js"></script>Via npm
npm install @mypatientspace/chatbot-widgetDevelopment
# Install dependencies
yarn install
# Start dev server (includes demo UI)
yarn dev
# Build for production
yarn build # Builds both widget and demo
yarn build:widget # Widget only
yarn build:demo # Demo only
# Preview production build
yarn previewWeb Integration
Minimal Setup
<script src="https://unpkg.com/@mypatientspace/chatbot-widget@latest/dist/mypatientspace-widget.umd.js"></script>
<script>
ChatbotWidget.init({
apiEndpoint: 'https://your-api.com',
token: 'your-auth-token'
});
</script>Full Customization
<script src="https://unpkg.com/@mypatientspace/chatbot-widget@latest/dist/mypatientspace-widget.umd.js"></script>
<script>
ChatbotWidget.init({
// API & Auth
apiEndpoint: 'https://your-api.com',
token: 'your-auth-token',
userType: 'patient', // 'patient' (default) or 'staff'
assistantId: 'your-assistant-id',
// Display mode
floatingMode: true, // false = embedded (default), true = FAB button
position: 'bottom-left', // FAB position (default: 'bottom-right')
hideExpandButton: true, // Hide expand/minimize button from header
showCloseSlot: true, // Empty placeholder for custom close button
// Content
headerTitle: 'Health Support',
headerSubtitle: 'Online now',
greeting: 'Hi! How can I help?',
placeholder: 'Ask me anything...',
brandingText: 'Powered by MyCompany',
disclaimerText: 'AI can make mistakes. Verify important information.',
headerIcon: '/logo.png',
fabIcon: '/avatar.png', // Only used in floating mode
quickActions: ['I need help', 'Book appointment'],
// Appearance
colorMode: 'system', // 'light', 'dark', or 'system' (auto-detect)
theme: {
colors: {
primary: '#ff6600', // FAB button, links, main accent
primaryDark: '#cc5200', // Hover states
secondary: '#2d3748', // Header background
headerText: '#ffffff', // Header text color
background: '#ffffff', // Chat window background
surface: '#f7fafc', // Input/card backgrounds
text: '#2d3748', // Primary text
textLight: '#718096', // Secondary text, timestamps
userBubble: '#ff6600', // User message background
userBubbleText: '#ffffff', // User message text
botBubble: '#edf2f7', // Bot message background
botBubbleText: '#2d3748', // Bot message text
},
fontFamily: 'Inter, system-ui, sans-serif',
borderRadius: '8px',
shadow: '0 4px 12px rgba(0, 0, 0, 0.1)',
},
// Callbacks
onOpen: () => console.log('Chat opened'),
onClose: () => console.log('Chat closed'),
onMessageSent: (message) => console.log('Sent:', message),
onMessageReceived: (message) => console.log('Received:', message),
onQuickAction: (action) => console.log('Quick action:', action),
onStreamChunk: (chunk) => console.log('Chunk:', chunk),
onCitationClick: (citation) => console.log('Citation:', citation),
onNewChat: () => console.log('New chat started'),
onWidgetReady: (api) => console.log('Widget ready:', api),
});
</script>Via npm import
import '@mypatientspace/chatbot-widget';
ChatbotWidget.init({
apiEndpoint: 'https://your-api.com'
});Patient & Staff Integration
The widget supports two user types with separate API routing. Each type uses different backend endpoints for chat, message history, and assistant lookup.
Patient (Default)
Patient mode is the default — no userType needed:
<script>
ChatbotWidget.init({
apiEndpoint: 'https://your-api.com',
token: 'your-auth-token'
});
</script>API endpoints used:
POST /api/patient/chat/stream— Send messagesGET /api/patient/chat/messages— Load historyGET /api/patient/assistant— Get assistant config
Staff
Staff mode requires userType: 'staff' along with contextPatientId and patientTypeId:
<script>
ChatbotWidget.init({
apiEndpoint: 'https://your-api.com',
token: 'your-auth-token',
userType: 'staff',
contextPatientId: 'patient-123',
patientTypeId: 'type-456'
});
</script>API endpoints used:
POST /api/staff/chat/stream— Send messages (includescontextPatientIdin body)GET /api/staff/chat/messages— Load history (requirescontextPatientIdquery param)GET /api/staff/assistant/{patientTypeId}— Get assistant config
Required Fields by User Type
| Field | Patient | Staff |
|-------|---------|-------|
| apiEndpoint | Required | Required |
| token | Required | Required |
| userType | Optional (default) | 'staff' |
| contextPatientId | Optional | Required |
| patientTypeId | - | Required |
API Methods
ChatbotWidget.open(); // Open chat window
ChatbotWidget.close(); // Close chat window
ChatbotWidget.toggle(); // Toggle open/close
ChatbotWidget.startNewChat(); // Clear session and start new chat
ChatbotWidget.update(config); // Update widget configuration
ChatbotWidget.destroy(); // Remove widget completelyEmbedded Mode
By default, the widget is embedded inside a container element. You can enable floating mode for a FAB button popup.
Using containerSelector
Embed the chat inside an existing element:
<div id="my-chat" style="width: 400px; height: 600px;"></div>
<script src="https://unpkg.com/@mypatientspace/chatbot-widget@latest/dist/mypatientspace-widget.umd.js"></script>
<script>
ChatbotWidget.init({
apiEndpoint: 'https://your-api.com',
containerSelector: '#my-chat'
});
</script>Using floatingMode
Enable floating mode with FAB button (classic chatbot style):
<script>
ChatbotWidget.init({
apiEndpoint: 'https://your-api.com',
floatingMode: true
});
</script>Comparison
| Feature | Embedded (default) | floatingMode: true |
|---------|-------------------|----------------------|
| FAB button | Hidden | Shown |
| Chat visibility | Always open | Opens on click |
| Position | Fills container | Fixed bottom-right/left |
| Sizing | 100% of parent | 380x520px |
Mobile Integration
Android (Kotlin)
class ChatActivity : AppCompatActivity() {
private lateinit var webView: WebView
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
webView = WebView(this).apply {
settings.javaScriptEnabled = true
settings.domStorageEnabled = true
loadDataWithBaseURL(
"https://your-domain.com",
"""
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1">
</head>
<body style="margin:0;padding:0;">
<script src="https://unpkg.com/@mypatientspace/chatbot-widget@latest/dist/mypatientspace-widget.umd.js"></script>
<script>
ChatbotWidget.init({
apiEndpoint: 'https://your-api.com'
});
ChatbotWidget.open();
</script>
</body>
</html>
""".trimIndent(),
"text/html", "UTF-8", null
)
}
setContentView(webView)
}
}iOS (Swift)
import UIKit
import WebKit
class ChatViewController: UIViewController {
var webView: WKWebView!
override func viewDidLoad() {
super.viewDidLoad()
let config = WKWebViewConfiguration()
config.preferences.javaScriptEnabled = true
webView = WKWebView(frame: view.bounds, configuration: config)
webView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
view.addSubview(webView)
let html = """
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
<style>body { margin: 0; padding: 0; }</style>
</head>
<body>
<script src="https://unpkg.com/@mypatientspace/chatbot-widget@latest/dist/mypatientspace-widget.umd.js"></script>
<script>
ChatbotWidget.init({
apiEndpoint: 'https://your-api.com'
});
ChatbotWidget.open();
</script>
</body>
</html>
"""
webView.loadHTMLString(html, baseURL: URL(string: "https://your-domain.com"))
}
}iOS (Objective-C)
#import <UIKit/UIKit.h>
#import <WebKit/WebKit.h>
@interface ChatViewController : UIViewController
@property (nonatomic, strong) WKWebView *webView;
@end
@implementation ChatViewController
- (void)viewDidLoad {
[super viewDidLoad];
WKWebViewConfiguration *config = [[WKWebViewConfiguration alloc] init];
config.preferences.javaScriptEnabled = YES;
self.webView = [[WKWebView alloc] initWithFrame:self.view.bounds configuration:config];
self.webView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
[self.view addSubview:self.webView];
NSString *html = @"<!DOCTYPE html>"
"<html>"
"<head>"
"<meta name='viewport' content='width=device-width, initial-scale=1, maximum-scale=1'>"
"<style>body { margin: 0; padding: 0; }</style>"
"</head>"
"<body>"
"<script src='https://unpkg.com/@mypatientspace/chatbot-widget@latest/dist/mypatientspace-widget.umd.js'></script>"
"<script>"
"ChatbotWidget.init({ apiEndpoint: 'https://your-api.com' });"
"ChatbotWidget.open();"
"</script>"
"</body>"
"</html>";
[self.webView loadHTMLString:html baseURL:[NSURL URLWithString:@"https://your-domain.com"]];
}
@endReact Native
import { WebView } from 'react-native-webview';
const ChatScreen = () => {
const html = `
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1">
</head>
<body style="margin:0;padding:0;">
<script src="https://unpkg.com/@mypatientspace/chatbot-widget@latest/dist/mypatientspace-widget.umd.js"></script>
<script>
ChatbotWidget.init({
apiEndpoint: 'https://your-api.com'
});
ChatbotWidget.open();
</script>
</body>
</html>
`;
return (
<WebView
source={{ html }}
javaScriptEnabled={true}
domStorageEnabled={true}
/>
);
};Configuration Reference
All Options
| Option | Type | Default | Description |
|--------|------|---------|-------------|
| apiEndpoint | string | - | Base API URL, e.g. https://your-api.com (widget offline if not set) |
| token | string | - | Auth token for API requests |
| userType | 'patient' \| 'staff' | 'patient' | User type for API endpoint routing |
| patientTypeId | string | - | Patient type ID for staff assistant lookup (required when userType is 'staff') |
| sessionId | string | - | Existing session ID to resume |
| assistantId | string | - | Specific assistant ID to use |
| contextPatientId | string | - | Patient context for the chat |
| loadHistory | boolean | true | Load previous chat history |
| colorMode | 'light' \| 'dark' \| 'system' | 'light' | Color mode for the widget |
| theme | ThemeConfig | - | Custom theme colors, fonts, border radius, shadow |
| position | 'bottom-right' \| 'bottom-left' | 'bottom-right' | FAB button position |
| containerSelector | string | - | CSS selector for embedded container |
| floatingMode | boolean | false | Show FAB button and floating chat |
| hideExpandButton | boolean | false | Hide the expand/minimize button from header |
| showCloseSlot | boolean | false | Show empty circle placeholder for custom close button |
| greeting | string | From API | Initial bot greeting message |
| placeholder | string | From API | Input field placeholder text |
| headerTitle | string | From API | Chat window header title |
| headerSubtitle | string | From API | Chat window header subtitle |
| headerIcon | string | From API | Header icon image URL |
| fabIcon | string | From API | FAB button image URL |
| brandingText | string | From API | Footer branding text |
| disclaimerText | string | From API | Disclaimer text below input area |
| quickActions | string[] | From API | Predefined quick action buttons |
Note: Content fields (
greeting,headerTitle,placeholder,brandingText,headerIcon,fabIcon,quickActions,disclaimerText) are loaded from the assistant's API configuration by default. Setting them in the widget config overrides the API values.
Callbacks
| Callback | Parameters | Description |
|----------|------------|-------------|
| onOpen | () | Called when chat window opens |
| onClose | () | Called when chat window closes |
| onMessageSent | (message: Message) | Called after user sends a message |
| onMessageReceived | (message: Message) | Called after bot response completes |
| onQuickAction | (action: string) | Called when quick action is clicked |
| onStreamChunk | (chunk: string) | Called for each streamed response chunk |
| onCitationClick | (citation: Citation) | Called when a content card is clicked |
| onNewChat | () | Called when user starts a new chat |
| onWidgetReady | (api: WidgetApi) | Called when widget is ready with API methods |
Available Theme Colors
| Color | Light Default | Description |
|-------|---------------|-------------|
| primary | #00c2d1 | FAB button, links, main accent |
| primaryDark | #017992 | Hover states |
| secondary | #3c4d73 | Header background |
| accent | #33b1e6 | Secondary accent color |
| accentLight | #b8ebff | Light accent |
| success | #00dec4 | Success states |
| info | #30d7ed | Info states |
| background | #ffffff | Chat window background |
| surface | #fdfefe | Input/card backgrounds |
| text | #3c4d73 | Primary text |
| textLight | #6b7280 | Secondary text, timestamps |
| userBubble | #00c2d1 | User message background |
| userBubbleText | #ffffff | User message text |
| botBubble | #e0f7fa | Bot message background |
| botBubbleText | #3c4d73 | Bot message text |
| border | #d1d5db | Border color |
| borderLight | #e5e7eb | Light border |
| error | #ef4444 | Error states |
| errorBackground | #fef2f2 | Error background |
| white | #ffffff | White color |
| recording | #ef4444 | Voice recording indicator |
| headerText | #ffffff | Header text and icon color |
| scrollbarThumb | rgba(60, 77, 115, 0.2) | Scrollbar thumb color |
| scrollbarThumbHover | rgba(60, 77, 115, 0.3) | Scrollbar thumb hover |
Default Fallback Values
Content fields are resolved with this priority: Config > Assistant API > Component default
| Field | Component Fallback |
|-------|-------------------|
| headerTitle | "AI Doctor" |
| greeting | "Hello! Welcome to our healthcare support. How can I assist you today?" |
| placeholder | "Type a message..." |
| brandingText | "Developed by myPatientSpace" |
| disclaimerText | "AI can make mistakes. Verify important information." |
| headerIcon | MPS logo |
| fabIcon | MPS logo |
| quickActions | Empty (from API only) |
License
MIT
