**Hanc WebRTC Widgets** is a Web Components library for easily integrating **Hanc AI voice call widgets** with stunning 3D audio-reactive orb visualizations into your website or web application.
npm install hanc-webrtc-widgetsHanc WebRTC Widgets is a Web Components library for easily integrating Hanc AI voice call widgets with stunning 3D audio-reactive orb visualizations into your website or web application.
It provides ready-to-use, customizable, and lightweight UI widgets for initiating AI-driven voice calls, with beautiful WebGL-powered visual feedback that responds to both AI and user voice in real-time.
You can use it in plain HTML, or integrate it with React, Next.js, Vue, or any other modern frontend stack.
- 🎨 Four Widget Types: Inline, Floating, Pill, and Pill Floating layouts
- 🌈 Audio-Reactive 3D Orb: WebGL-powered visualization responding to voice
- 🎭 Color Presets: Dark and light theme color palettes
- 🔧 Highly Customizable: Full control over colors, glow, animations, and behavior
- 🚀 Zero Dependencies: Works standalone or with any framework
- 📦 Tiny Bundle: Optimized for performance
- ♿ Accessible: Built with Web Components standards
- 🎯 CLS Optimized: No layout shifts
``html
src="https://unpkg.com/hanc-webrtc-widgets"
async
type="text/javascript"
>
size="300"
>
position="bottom-right"
size="120"
>
button-start-text="Talk to AI Agent"
orb-size="48"
>
position="bottom-right"
button-start-text="Talk to AI"
>
`
`bash`
npm install hanc-webrtc-widgets
1. Install dependencies:
`bash`
npm install @lit/react hanc-webrtc-widgets
2. Create React wrappers:
`tsx
import React from 'react';
import { createComponent } from '@lit/react';
import { InlineCall, FloatingCall, PillCall, PillFloatingCall } from 'hanc-webrtc-widgets';
export const HancAiInlineCall = createComponent({
tagName: 'hanc-ai-inline-call',
elementClass: InlineCall,
react: React,
events: {
onCallStart: 'call-start',
onCallEnd: 'call-end',
},
});
export const HancAiFloatingCall = createComponent({
tagName: 'hanc-ai-floating-call',
elementClass: FloatingCall,
react: React,
events: {
onCallStart: 'call-start',
onCallEnd: 'call-end',
},
});
export const HancAiPillCall = createComponent({
tagName: 'hanc-ai-pill-call',
elementClass: PillCall,
react: React,
events: {
onCallStart: 'call-start',
onCallEnd: 'call-end',
},
});
export const HancAiPillFloatingCall = createComponent({
tagName: 'hanc-ai-pill-floating-call',
elementClass: PillFloatingCall,
react: React,
events: {
onCallStart: 'call-start',
onCallEnd: 'call-end',
},
});
`
3. Use in your components:
`tsx
import { darkPresets, lightPresets } from 'hanc-webrtc-widgets';
export default function Example() {
return (
<>
{/ Inline widget with custom colors /}
size={300}
orbColors={darkPresets.emerald}
glowIntensity={1.2}
/>
{/ Floating widget in top-left /}
position="top-left"
orbColors={darkPresets.rose}
/>
{/ Pill button /}
buttonStartText="Talk to AI"
orbColors={lightPresets.indigo}
/>
{/ Floating pill button /}
position="bottom-right"
buttonStartText="Chat with AI"
/>
>
);
}
`
1. Install dependencies:
`bash`
npm install @lit/react hanc-webrtc-widgets
2. Create a wrapper component with dynamic import:
`tsx
'use client';
import React from 'react';
import dynamic from 'next/dynamic';
import { createComponent } from '@lit/react';
export const HancAiInlineCall = dynamic(
async () => {
const { InlineCall } = await import('hanc-webrtc-widgets');
return createComponent({
tagName: 'hanc-ai-inline-call',
elementClass: InlineCall,
react: React,
events: {
onCallStart: 'call-start',
onCallEnd: 'call-end',
},
});
},
{ ssr: false }
);
export const HancAiFloatingCall = dynamic(
async () => {
const { FloatingCall } = await import('hanc-webrtc-widgets');
return createComponent({
tagName: 'hanc-ai-floating-call',
elementClass: FloatingCall,
react: React,
events: {
onCallStart: 'call-start',
onCallEnd: 'call-end',
},
});
},
{ ssr: false }
);
export const HancAiPillCall = dynamic(
async () => {
const { PillCall } = await import('hanc-webrtc-widgets');
return createComponent({
tagName: 'hanc-ai-pill-call',
elementClass: PillCall,
react: React,
events: {
onCallStart: 'call-start',
onCallEnd: 'call-end',
},
});
},
{ ssr: false }
);
export const HancAiPillFloatingCall = dynamic(
async () => {
const { PillFloatingCall } = await import('hanc-webrtc-widgets');
return createComponent({
tagName: 'hanc-ai-pill-floating-call',
elementClass: PillFloatingCall,
react: React,
events: {
onCallStart: 'call-start',
onCallEnd: 'call-end',
},
});
},
{ ssr: false }
);
`
3. Use in your pages:
`tsx
'use client';
import { HancAiInlineCall, HancAiFloatingCall, HancAiPillCall } from '@/components/hanc-widgets';
import { darkPresets } from 'hanc-webrtc-widgets';
export default function Home() {
return (
orbColors={darkPresets.purple}
/>
position="bottom-right"
/>
);
}
`
`vue
:size="300"
@call-start="handleCallStart"
@call-end="handleCallEnd"
/>
position="bottom-right"
/>
button-start-text="Chat with AI"
/>
position="bottom-right"
button-start-text="Talk to AI"
/>
`
An inline widget that embeds directly in your page content. Features a large, prominent orb visualization with button overlay.
#### Quick Start Attributes
The essentials to get started:
| Attribute | Type | Default | Description |
|-----------|------|---------|-------------|
| agent-id (required) | string | - | Your Hanc AI agent ID |theme
| | string | "default" | Theme name: "default", "emerald", "rose", "amber", "cyan", "purple", "blue", "white", "black", "orange" |theme-mode
| | string | "auto" | "auto" (system), "dark", or "light" |size
| | number | 370 | Container size in pixels (responsive - scales down on smaller screens) |container-padding
| | number | 45 | Padding around orb (orb size = size - padding * 2) |button-start-text
| | string | "Start Call" | Button text |
#### All Attributes
| Attribute | Type | Default | Description |
|-----------|------|---------|-------------|
| agent-id (required) | string | - | Hanc AI agent ID |voice-service-url
| | string | - | Optional custom voice service URL |button-start-text
| | string | "Start Call" | Button text in idle state |button-connecting-text
| | string | "Connecting..." | Button text when connecting |size
| | number | 370 | Container size in pixels (responsive on small screens) |container-padding
| | number | 45 | Padding around orb (orb size = size - padding * 2) |theme
| | string | "default" | Theme name (e.g., "emerald", "rose") - see Themes section |theme-mode
| | string | "auto" | Theme mode: "auto", "dark", or "light" |orb-colors
| | object | Default preset | Color configuration object (see Color Presets) |glow-intensity
| | number | 0.8 | Glow effect strength (0-2) |idle-glow-multiplier
| | number | 0.4 | Glow multiplier in idle state |morph-strength
| | number | 1.0 | Audio-driven deformation strength |noise-scale
| | number | 1.5 | Noise pattern scale |noise-speed
| | number | 0.3 | Noise animation speed |fresnel-power
| | number | 2.5 | Edge glow (Fresnel) effect power |rotation-speed
| | number | 0.1 | Orb rotation speed |audio-reactivity
| | number | 3.0 | Audio response multiplier |audio-smoothing
| | number | 0.9 | Audio smoothing (0.1 = slow, 1.0 = instant) |idle-morph-multiplier
| | number | 0.25 | Morph strength in idle state |color-contrast
| | number | 1.5 | Color pattern sharpness |
#### Events
| Event | Description |
|-------|-------------|
| call-start | Fired when call successfully connects |call-end
| | Fired when call ends |
#### CSS Parts
| Part | Description |
|------|-------------|
| container | Outer container |orb-container
| | Orb canvas container |button
| | Call button |
#### Example
`html
size="300"
button-start-text="Talk to AI"
glow-intensity="1.2"
audio-reactivity="4.0"
>
`
---
A floating widget that stays fixed in a corner of the viewport. Perfect for persistent AI assistant access.
#### Quick Start Attributes
The essentials to get started:
| Attribute | Type | Default | Description |
|-----------|------|---------|-------------|
| agent-id (required) | string | - | Your Hanc AI agent ID |position
| | string | "bottom-right" | Corner position: "bottom-right", "bottom-left", "top-right", "top-left" |theme
| | string | "default" | Theme name: "default", "emerald", "rose", "amber", "cyan", "purple", "blue", "white", "black", "orange" |theme-mode
| | string | "auto" | "auto" (system), "dark", or "light" |size
| | number | 120 | Widget size in pixels |
#### All Attributes
All attributes from , plus:
| Attribute | Type | Default | Description |
|-----------|------|---------|-------------|
| position | string | "bottom-right" | Corner position: "bottom-right", "bottom-left", "top-right", "top-left", or "static" |button-start-text
| | string | "Call" | Shorter default text for compact layout |size
| | number | 120 | Widget size in pixels (smaller default) |theme
| | string | "default" | Theme name - see Themes section |theme-mode
| | string | "auto" | Theme mode: "auto", "dark", or "light" |
#### Example
`html
position="bottom-right"
>
position="top-left"
size="150"
>
position="static"
>
`
---
A horizontal pill-shaped button with orb on the left side. Ideal for minimal interfaces and inline CTAs.
#### Quick Start Attributes
The essentials to get started:
| Attribute | Type | Default | Description |
|-----------|------|---------|-------------|
| agent-id (required) | string | - | Your Hanc AI agent ID |theme
| | string | "default" | Theme name: "default", "emerald", "rose", "amber", "cyan", "purple", "blue", "white", "black", "orange" |theme-mode
| | string | "auto" | "auto" (system), "dark", or "light" |button-start-text
| | string | "Talk to AI Agent" | Button text when idle |orb-size
| | number | 48 | Orb diameter in pixels |
#### All Attributes
Same attributes as , plus:
| Attribute | Type | Default | Description |
|-----------|------|---------|-------------|
| button-start-text | string | "Talk to AI Agent" | Button text in idle state |button-end-text
| | string | "End call" | Button text when connected |orb-size
| | number | 48 | Orb diameter in pixels |theme
| | string | "default" | Theme name - see Themes section |theme-mode
| | string | "auto" | Theme mode: "auto", "dark", or "light" |
#### Example
`html
button-start-text="Chat with Support"
button-end-text="End Chat"
orb-size="48"
>
`
---
A floating pill-shaped button that stays fixed in a corner of the viewport. Combines the compact pill design with floating positioning for persistent AI assistant access.
#### Quick Start Attributes
The essentials to get started:
| Attribute | Type | Default | Description |
|-----------|------|---------|-------------|
| agent-id (required) | string | - | Your Hanc AI agent ID |position
| | string | "bottom-right" | Corner position: "bottom-right", "bottom-left", "top-right", "top-left", or "static" |theme
| | string | "default" | Theme name: "default", "emerald", "rose", "amber", "cyan", "purple", "blue", "white", "black", "orange" |theme-mode
| | string | "auto" | "auto" (system), "dark", or "light" |button-start-text
| | string | "Talk to AI Agent" | Button text when idle |orb-size
| | number | 48 | Orb diameter in pixels |
#### All Attributes
Same attributes as , plus:
| Attribute | Type | Default | Description |
|-----------|------|---------|-------------|
| position | string | "bottom-right" | Corner position: "bottom-right", "bottom-left", "top-right", "top-left", or "static" |button-start-text
| | string | "Talk to AI Agent" | Button text in idle state |button-end-text
| | string | "End call" | Button text when connected |button-connecting-text
| | string | "Connecting..." | Button text when connecting |orb-size
| | number | 48 | Orb diameter in pixels |theme
| | string | "default" | Theme name - see Themes section |theme-mode
| | string | "auto" | Theme mode: "auto", "dark", or "light" |
#### Example
`html
position="bottom-right"
button-start-text="Chat with AI"
>
position="top-left"
orb-size="56"
button-start-text="Need help?"
>
position="static"
theme="emerald"
>
`
---
The library includes professional color presets optimized for dark and light backgrounds.
`javascript
import { darkPresets, lightPresets, getColorPreset } from 'hanc-webrtc-widgets';
// Apply a preset
const widget = document.querySelector('hanc-ai-inline-call');
widget.orbColors = darkPresets.emerald;
// Or use the helper function
widget.orbColors = getColorPreset('rose', 'dark');
`
Optimized for dark backgrounds (default for floating/inline widgets):
- default - Indigo/Purple/Cyanemerald
- - Emerald green tonesrose
- - Rose/Pink tonesamber
- - Warm amber/orangecyan
- - Cool cyan/turquoisepurple
- - Deep purple/violetblue
- - Classic bluewhite
- - Silver/white tonesblack
- - Dark charcoal/graphiteorange
- - Vivid orange
Optimized for light backgrounds (default for pill widget):
- indigo - Deep indigoviolet
- - Rich violetteal
- - Ocean tealorange
- - Warm orangeblue
- - Vibrant bluepink
- - Hot pinksilver
- - Soft gray/silvercharcoal
- - Deep black/charcoaldeepOrange
- - Rich deep orange
`javascript
const widget = document.querySelector('hanc-ai-inline-call');
widget.orbColors = {
primary: '#6366f1', // Main orb color
secondary: '#8b5cf6', // Secondary color for patterns
accent: '#06b6d4', // Accent highlights
glow: '#818cf8', // Outer glow color
atmosphere: '#c4b5fd', // Atmospheric haze
depth: '#312e81', // Deep shadow color
highlight: '#e0e7ff' // Bright highlight color
};
`
`javascript
// For dark backgrounds
widget.glowIntensity = 0.8;
widget.idleGlowMultiplier = 0.4;
// For light backgrounds (more visible)
widget.glowIntensity = 1.5;
widget.idleGlowMultiplier = 1.0;
`
---
Themes combine colors and glow settings into ready-to-use configurations. Each theme includes both dark and light variants that automatically detect and match your system's color scheme by default.
The simplest way - just set the theme attribute:
`html
theme="emerald"
theme-mode="auto"
>
theme="rose"
theme-mode="dark"
>
theme="cyan"
>
`
`javascript
import { themes, getTheme, applyTheme, detectSystemTheme, watchSystemTheme } from 'hanc-webrtc-widgets';
// Get a complete theme configuration (auto-detects system by default)
const theme = getTheme('emerald', 'auto');
console.log(theme);
// {
// colors: { primary: '#10b981', secondary: '#34d399', ... },
// glowIntensity: 1.2,
// idleGlowMultiplier: 0.6
// }
// Detect system theme
const systemTheme = detectSystemTheme(); // Returns 'dark' or 'light'
// Apply theme to a widget
const widget = document.querySelector('hanc-ai-inline-call');
applyTheme(widget, 'rose', 'auto');
// Watch for system theme changes and update automatically
const stopWatching = watchSystemTheme(widget, 'emerald');
// Call stopWatching() to cleanup when done
// Or access theme structure directly
const emeraldTheme = themes.emerald;
widget.orbColors = emeraldTheme.dark.colors;
widget.glowIntensity = emeraldTheme.dark.glowIntensity;
`
All themes include both dark and light variants that automatically switch based on system preference:
- default - Indigo/Purple/Cyan (subtle in dark, vibrant in light)emerald
- - Fresh emerald green tonesrose
- - Elegant rose/pink paletteamber
- - Warm amber/orange huescyan
- - Cool cyan/turquoise shadespurple
- - Deep purple/violet colorsblue
- - Classic blue spectrumwhite
- - Silver/white (soft glow in dark, muted gray in light)black
- - Charcoal/graphite (subtle in dark, bold contrast in light)orange
- - Vivid orange (bright in dark, deep rich orange in light)
Dark variants are optimized for dark backgrounds with subtle glow.
Light variants are optimized for light backgrounds with stronger, more visible glow.
The widgets automatically detect and respond to your system's color scheme preference:
`javascript
import { detectSystemTheme, watchSystemTheme } from 'hanc-webrtc-widgets';
// Check current system preference
const isDark = detectSystemTheme() === 'dark';
// Automatically update widget when system theme changes
const widget = document.querySelector('hanc-ai-inline-call');
const cleanup = watchSystemTheme(widget, 'emerald');
// The widget will now automatically switch between
// emerald.dark and emerald.light based on system preference
// Cleanup when component unmounts
cleanup();
`
Use Themes when:
- You want quick, professional-looking results
- You need consistent styling across light/dark backgrounds
- You want the recommended glow settings
Use Manual Configuration when:
- You need precise control over individual colors
- You want custom brand colors
- You're fine-tuning for specific design requirements
`html
theme="emerald"
>
theme="rose"
theme-mode="dark"
>
glow-intensity="1.2"
idle-glow-multiplier="0.6"
>
`
---
The orb visualization is fully customizable with dozens of parameters. Here's what you can tweak to make it perfect for your design.
Control how the orb looks and glows:
`html`
glow-intensity="1.2"
fresnel-power="2.5"
color-contrast="1.5"
noise-scale="1.5"
>
Glow Settings:
- glow-intensity (0.5 - 2.0, default: 0.8) - How bright the outer glow appears. Higher = more dramatic glow effectidle-glow-multiplier
- (0 - 1.0, default: 0.4) - Glow brightness when nobody's talking. Lower = more subtle when idlefresnel-power
- (1.0 - 5.0, default: 2.5) - Edge highlight intensity. Higher = sharper, brighter edge glow
Color & Texture:
- color-contrast (1.0 - 3.0, default: 1.5) - Sharpness of the color pattern. Higher = more defined color bandsnoise-scale
- (1.0 - 3.0, default: 1.5) - Detail level of the surface texture. Higher = more intricate patterns
Make the orb respond to voice input:
`html`
audio-reactivity="3.0"
audio-smoothing="0.9"
morph-strength="1.0"
>
Response Intensity:
- audio-reactivity (1.0 - 5.0, default: 3.0) - How strongly the orb reacts to audio. Higher = more dramatic pulsing and movementmorph-strength
- (0.5 - 2.0, default: 1.0) - How much the orb deforms when responding to voice. Higher = more shape-shifting
Smoothness:
- audio-smoothing (0.1 - 1.0, default: 0.9) - How smooth the audio reaction is. Lower = gentle flowing motion, Higher = snappy response
Configure how the orb moves when nobody's talking:
`html`
idle-morph-multiplier="0.25"
rotation-speed="0.1"
noise-speed="0.3"
>
Idle Animation:
- idle-morph-multiplier (0 - 1.0, default: 0.25) - How much the orb "breathes" when idle. Higher = more movementrotation-speed
- (0 - 1.0, default: 0.1) - Rotation speed. Higher = faster spinningnoise-speed
- (0 - 1.0, default: 0.3) - Pattern animation speed. Higher = faster flowing patterns
Here's a custom configuration that creates a high-energy, reactive orb:
`html
theme="emerald"
glow-intensity="1.5"
idle-glow-multiplier="0.6"
fresnel-power="3.0"
audio-reactivity="4.0"
audio-smoothing="0.85"
morph-strength="1.2"
color-contrast="2.0"
noise-scale="2.0"
idle-morph-multiplier="0.5"
rotation-speed="0.2"
noise-speed="0.5"
>
`
For subtle, professional look:
- Lower glow-intensity (0.6 - 0.8)audio-reactivity
- Lower (2.0 - 2.5)idle-morph-multiplier
- Lower (0.1 - 0.2)
For energetic, eye-catching look:
- Higher glow-intensity (1.2 - 1.8)audio-reactivity
- Higher (3.5 - 4.5)morph-strength
- Higher (1.2 - 1.5)
For smooth, flowing animations:
- Lower audio-smoothing (0.7 - 0.85)rotation-speed
- Lower (0.05 - 0.1)
For responsive, snappy animations:
- Higher audio-smoothing (0.9 - 0.95)noise-speed
- Higher (0.5 - 0.7)
---
All widgets support CSS parts for custom styling:
`css
/ Style the button /
hanc-ai-inline-call::part(button) {
font-family: 'Inter', sans-serif;
}
/ Change container background /
hanc-ai-floating-call::part(container) {
background: rgba(0, 0, 0, 0.1);
backdrop-filter: blur(10px);
}
/ Style the pill button /
hanc-ai-pill-call::part(pill-button) {
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.2);
}
`
---
All widgets emit the same events:
Fired when the AI call successfully connects.
`javascript`
widget.addEventListener('call-start', () => {
console.log('Call started');
// Update UI, start timer, etc.
});
Fired when the call ends (user hangup or error).
`javascript`
widget.addEventListener('call-end', () => {
console.log('Call ended');
// Clean up, show feedback form, etc.
});
---
Widgets play notification sounds when a call starts and ends. Four built-in sound presets are available, synthesized using Web Audio API for a professional feel.
`html
sound-preset="1"
sound-volume="0.5"
>
sound-preset="none"
>
`
| Preset | Name | Description |
|--------|------|-------------|
| 1 | Drop | Water drop sound with pitch glide |2
| | Glass Tap | Crystal clear high-frequency tap |3
| | Soft Whoosh | Airy swoosh with noise texture |4
| | Gentle Note | Soft musical note with harmonics |none
| | Disabled | No notification sounds |
| Attribute | Type | Default | Description |
|-----------|------|---------|-------------|
| sound-preset | string | "1" | Sound preset: "1", "2", "3", "4", or "none" |sound-volume
| | number | 0.3 | Volume level from 0.0 to 1.0 |
`javascript
import { SoundManager } from 'hanc-webrtc-widgets';
// Create a standalone sound manager
const sound = new SoundManager({
preset: '3',
volume: 0.5,
enabled: true
});
// Play sounds manually
await sound.playCallStartSound();
await sound.playCallEndSound();
// Change settings
sound.setPreset('2');
sound.setVolume(0.7);
sound.setEnabled(false);
// Cleanup
sound.destroy();
`
---
- ✅ Chrome/Edge 90+
- ✅ Firefox 88+
- ✅ Safari 15.4+
- ✅ Opera 76+
Requires support for:
- Web Components (Custom Elements v1)
- Shadow DOM v1
- WebGL 2.0
- Web Audio API
- WebRTC
---
- Bundle Size: ~320KB gzipped (includes Three.js for WebGL rendering)
- Performance: 60 FPS on modern hardware
- CLS Optimized: Fixed dimensions prevent layout shifts
- Lazy Loading: Load widgets on demand with dynamic imports
---
Full TypeScript support with exported types:
`typescript
import type { OrbColors } from 'hanc-webrtc-widgets';
const customColors: OrbColors = {
primary: '#6366f1',
secondary: '#8b5cf6',
accent: '#06b6d4',
glow: '#818cf8',
atmosphere: '#c4b5fd',
depth: '#312e81',
highlight: '#e0e7ff'
};
``
---
MIT
---
For issues, questions, or feature requests, please visit our GitHub repository.