Widgets
Drop-in floating UI components for chat and voice. Zero custom UI code needed — just configure and go.
ℹ When to use widgets vs. custom UI
Widgets are pre-built floating UIs (chat bubble, voice button) — great for quickly adding AI to any page. If you need full control over the design, use the XpectrumChat / XpectrumVoice classes directly and build your own UI.
1. ChatWidget
A floating chat bubble that opens into a full chat window. Uses Shadow DOM for style isolation — it won't conflict with your existing CSS.
Basic usage
import { ChatWidget } from '@xpectrum/sdk';
const widget = new ChatWidget({
apiKey: 'app-xxxxxxxxxxxx',
baseUrl: 'https://app.yourserver.com/api/v1',
});
// Control programmatically
widget.open();
widget.close();
widget.toggle();
widget.destroy(); // Remove completelyAll config options
| Property | Type | Required | Default | Description |
|---|---|---|---|---|
| apiKey | string | Yes | — | Bearer token for chat API. |
| baseUrl | string | Yes | — | Chat API endpoint URL. |
| container | HTMLElement | No | document.body | DOM element to mount the widget into. |
| position | 'bottom-right' | 'bottom-left' | No | 'bottom-right' | Where the floating button appears. |
| buttonColor | string | No | #7C3AED | Hex color for the floating button. |
| buttonSize | number | No | 48 | Button diameter in pixels. |
| theme | 'light' | 'dark' | 'auto' | No | 'light' | Color theme for the chat window. |
| zIndex | number | No | 2147483647 | CSS z-index for the widget. |
| welcomeMessage | string | No | — | Initial message shown when chat opens. |
| user | string | No | — | Unique user identifier for conversation history. |
| windowWidth | number | No | 400 | Chat window width in pixels. |
| windowHeight | number | No | 600 | Chat window height in pixels. |
Customized example
const widget = new ChatWidget({
apiKey: 'app-xxxxxxxxxxxx',
baseUrl: 'https://app.yourserver.com/api/v1',
position: 'bottom-left',
buttonColor: '#10b981',
buttonSize: 56,
theme: 'dark',
welcomeMessage: 'Hi there! How can I help you today?',
user: 'user-123',
windowWidth: 450,
windowHeight: 650,
});Features
- Shadow DOM for complete style isolation
- Auto-resizing textarea for message input
- Real-time message streaming with typing indicator
- Conversation persistence across sessions
- ESC key to close, Enter to send (Shift+Enter for newline)
- Loads app parameters (opening statement, suggested questions) on first open
2. VoiceWidget
A floating button that opens a voice call interface with live transcription.
Basic usage
import { VoiceWidget } from '@xpectrum/sdk';
const widget = new VoiceWidget({
apiKey: 'xpectrum_ai_sk_...',
agentName: '6b00c03f-...',
baseUrl: 'https://api.xpectrum.co/',
});
widget.open();
widget.close();
widget.toggle();
widget.destroy();All config options
| Property | Type | Required | Default | Description |
|---|---|---|---|---|
| apiKey | string | Yes | — | API key for voice auth (x-api-key header). |
| agentName | string | Yes | — | Agent UUID or name to connect to. |
| baseUrl | string | Yes | — | Voice server URL. |
| container | HTMLElement | No | document.body | DOM element to mount into. |
| position | 'bottom-right' | 'bottom-left' | No | 'bottom-right' | Floating button position. |
| buttonColor | string | No | #7C3AED | Hex color for the button. |
| buttonSize | number | No | 48 | Button diameter in pixels. |
| zIndex | number | No | 2147483647 | CSS z-index. |
| windowWidth | number | No | 360 | Voice window width in pixels. |
| windowHeight | number | No | 480 | Voice window height in pixels. |
| onTranscription | (segment) => void | No | — | External callback for transcription events. |
| onStateChange | (state) => void | No | — | External callback for connection state changes. |
Features
- Start/hang up call buttons
- Mute/unmute microphone button
- Real-time transcription display (last 50 segments)
- Color-coded connection status (gray=disconnected, amber=connecting, green=connected, red=failed)
- Auto-disconnect when widget closes
3. OmnichannelWidget
A single floating button that offers both Chat and Voice options in a menu. Manages both widgets internally.
import { OmnichannelWidget } from '@xpectrum/sdk';
const widget = new OmnichannelWidget({
// Chat config
chatBaseUrl: 'https://app.yourserver.com/api/v1',
chatApiKey: 'app-xxxxxxxxxxxx',
// Voice config
voiceBaseUrl: 'https://api.xpectrum.co/',
apiKey: 'xpectrum_ai_sk_...',
agentName: '6b00c03f-...',
// Shared options
position: 'bottom-right',
buttonColor: '#7C3AED',
user: 'user-123',
});
// Programmatic control
widget.openChat();
widget.openVoice();
widget.close();
widget.destroy();| Property | Type | Required | Default | Description |
|---|---|---|---|---|
| chatBaseUrl | string | Yes | — | Chat API endpoint URL. |
| chatApiKey | string | Yes | — | Chat API key (Bearer token). |
| voiceBaseUrl | string | Yes | — | Voice server URL. |
| apiKey | string | Yes | — | Voice API key (x-api-key). |
| agentName | string | Yes | — | Voice agent UUID. |
| container | HTMLElement | No | document.body | Mount point. |
| position | 'bottom-right' | 'bottom-left' | No | 'bottom-right' | Button position. |
| buttonColor | string | No | — | Hex color for the main button. |
| zIndex | number | No | — | CSS z-index. |
| user | string | No | — | User ID for chat history. |
| chat | Partial<ChatWidgetConfig> | No | — | Override any ChatWidget config. |
| voice | Partial<VoiceWidgetConfig> | No | — | Override any VoiceWidget config. |
4. Embed via Script Tag (No Build Step)
For plain HTML pages, you can add widgets with just a script tag — no npm install or build step needed.
Chat embed
<script>
window.XpectrumChatConfig = {
apiKey: 'app-xxxxxxxxxxxx',
baseUrl: 'https://app.yourserver.com/api/v1',
position: 'bottom-right',
buttonColor: '#7C3AED',
theme: 'light',
welcomeMessage: 'Hi! How can I help?',
};
</script>
<script src="https://unpkg.com/@xpectrum/sdk/dist/chat-embed.min.js" defer></script>Voice embed
<script>
window.XpectrumVoiceConfig = {
token: 'xpectrum_ai_sk_...',
baseUrl: 'https://api.xpectrum.co/',
position: 'bottom-right',
buttonColor: '#7C3AED',
};
</script>
<script src="https://unpkg.com/@xpectrum/sdk/dist/voice-embed.min.js" defer></script>5. Using Widgets in React / Next.js
⚠ Client component required
'use client' at the top of your file in Next.js App Router.'use client';
import { useEffect, useRef } from 'react';
import { ChatWidget } from '@xpectrum/sdk';
export default function ChatBubble() {
const widgetRef = useRef<ChatWidget | null>(null);
useEffect(() => {
widgetRef.current = new ChatWidget({
apiKey: process.env.NEXT_PUBLIC_CHAT_API_KEY!,
baseUrl: process.env.NEXT_PUBLIC_CHAT_BASE_URL!,
position: 'bottom-right',
buttonColor: '#7C3AED',
theme: 'auto',
welcomeMessage: 'Hello! How can I help you today?',
});
return () => widgetRef.current?.destroy();
}, []);
return null; // Widget manages its own DOM
}Then use it in any page or layout:
import ChatBubble from './components/ChatBubble';
export default function RootLayout({ children }) {
return (
<html lang="en">
<body>
{children}
<ChatBubble />
</body>
</html>
);
}