React Integration
Learn how to integrate Sibilance voice surveys into your React applications using the provided React hooks and components.
Overview
Sibilance provides React-specific exports for seamless integration:
- useSibilance - Hook to access survey state and controls
- FloatingMicButton - Pre-built floating microphone button component
- SurveyState - Access to survey progress and collected data
Installation
bash
npm install @sibilance.is/clientBasic Setup
1. Use the Hook
The useSibilance hook provides everything you need:
tsx
import { useSibilance, FloatingMicButton } from '@sibilance.is/client/react';
function VoiceSurvey() {
const { voiceState, surveyState, toggleSession } = useSibilance({
surveyKey: process.env.NEXT_PUBLIC_SIBILANCE_SURVEY_KEY!,
}, {
onComplete: (yaml) => {
console.log('Survey completed!', yaml);
// Submit to your backend
fetch('/api/survey-results', {
method: 'POST',
body: JSON.stringify({ results: yaml })
});
}
});
return (
<FloatingMicButton
isConnected={voiceState.isConnected}
onClick={toggleSession}
/>
);
}Hook API
useSibilance
typescript
const {
voiceState, // Voice session state
surveyState, // Survey progress state
toggleSession, // Start/stop voice session
complete, // Manually complete survey
pause // Pause survey
} = useSibilance(config, callbacks);Configuration
typescript
interface SibilanceConfig {
surveyKey?: string; // Survey key (production mode)
survey?: SurveyConfig; // Direct config (editor/test mode)
backendUrl?: string; // Optional: Custom backend URL
autoStart?: boolean; // Optional: Auto-start voice session
customInstructions?: string; // Optional: Additional AI instructions
}Callbacks
typescript
interface SurveyCallbacks {
onComplete?: (yaml: any[]) => void;
onPause?: () => void;
onRecordInformation?: (info: CollectedInformation) => void;
onLogConversation?: (speaker: 'ai' | 'user', message: string) => void;
onError?: (error: Error) => void;
onStepChange?: (stepId: string) => void;
}Voice State
Access voice session state:
tsx
function VoiceStatus() {
const { voiceState } = useSibilance({
surveyKey: 'sibilance_your_key_here'
});
return (
<div>
<p>Connected: {voiceState.isConnected ? 'Yes' : 'No'}</p>
<p>User Speaking: {voiceState.isUserSpeaking ? 'Yes' : 'No'}</p>
<p>AI Speaking: {voiceState.isAISpeaking ? 'Yes' : 'No'}</p>
<p>AI Thinking: {voiceState.isAIThinking ? 'Yes' : 'No'}</p>
</div>
);
}Survey State
Track survey progress:
tsx
function SurveyProgress() {
const { surveyState } = useSibilance({
surveyKey: 'sibilance_your_key_here'
});
return (
<div>
{surveyState.isActive && (
<>
<p>Survey in progress...</p>
<p>Current step: {surveyState.currentStepId}</p>
<p>Collected info: {surveyState.collectedInfo.length} items</p>
<p>Conversation log: {surveyState.conversationLog.length} entries</p>
</>
)}
{surveyState.isComplete && (
<p>Survey completed!</p>
)}
</div>
);
}Components
FloatingMicButton
Pre-built floating microphone button component.
tsx
import { FloatingMicButton } from '@sibilance.is/client/react';
function App() {
const { voiceState, toggleSession } = useSibilance({
surveyKey: 'sibilance_your_key_here'
});
return (
<FloatingMicButton
isConnected={voiceState.isConnected}
onClick={toggleSession}
position="bottom-right"
/>
);
}Props:
isConnected- Whether voice session is active (required)onClick- Toggle session function (required)position-'bottom-right' | 'bottom-left' | 'top-right' | 'top-left'(default:'bottom-right')className- Additional CSS classesstyle- Inline styles
Common Patterns
Auto-Start Survey
tsx
function AutoStartSurvey() {
const { toggleSession } = useSibilance({
surveyKey: 'sibilance_your_key_here',
autoStart: true
}, {
onComplete: (yaml) => {
console.log('Survey completed!', yaml);
}
});
return <YourApp />;
}Conditional Rendering Based on State
tsx
function SurveyStatus() {
const { voiceState, surveyState } = useSibilance({
surveyKey: 'sibilance_your_key_here'
});
return (
<div>
{voiceState.isConnected && (
<div className="status-indicator">
{voiceState.isUserSpeaking && <span>🎤 Listening...</span>}
{voiceState.isAIThinking && <span>🤔 Thinking...</span>}
{voiceState.isAISpeaking && <span>🔊 Speaking...</span>}
</div>
)}
{surveyState.isActive && (
<div className="survey-progress">
<p>Step: {surveyState.currentStepId}</p>
<p>Collected: {surveyState.collectedInfo.length} items</p>
</div>
)}
{surveyState.isComplete && (
<div className="survey-complete">
<p>✅ Survey completed!</p>
</div>
)}
</div>
);
}Handle Survey Completion
tsx
function SurveyHandler() {
const { surveyState } = useSibilance({
surveyKey: 'sibilance_your_key_here'
}, {
onComplete: async (yaml) => {
// Submit results to your backend
const response = await fetch('/api/survey-results', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ results: yaml })
});
if (response.ok) {
console.log('Results submitted successfully!');
}
}
});
return <YourApp />;
}Track Collected Information
tsx
function InformationTracker() {
const { surveyState } = useSibilance({
surveyKey: 'sibilance_your_key_here'
}, {
onRecordInformation: (info) => {
console.log('Information recorded:', info);
// info: { field: string, value: string, sourceStep?: string, timestamp: number }
}
});
return (
<div>
<h3>Collected Information</h3>
<ul>
{surveyState.collectedInfo.map((info, i) => (
<li key={i}>
<strong>{info.field}:</strong> {info.value}
{info.sourceStep && <span> (from {info.sourceStep})</span>}
</li>
))}
</ul>
</div>
);
}Conversation Log
tsx
function ConversationLog() {
const { surveyState } = useSibilance({
surveyKey: 'sibilance_your_key_here'
});
return (
<div className="conversation-log">
<h3>Conversation</h3>
{surveyState.conversationLog.map((entry, i) => (
<div key={i} className={`entry ${entry.speaker}`}>
<strong>{entry.speaker === 'ai' ? 'AI' : 'User'}:</strong>
<p>{entry.message}</p>
<small>{new Date(entry.timestamp).toLocaleTimeString()}</small>
</div>
))}
</div>
);
}Complete Example
tsx
// App.tsx
import { useSibilance, FloatingMicButton } from '@sibilance.is/client/react';
import { useState, useEffect } from 'react';
function App() {
const [results, setResults] = useState<any[]>([]);
const { voiceState, surveyState, toggleSession } = useSibilance({
surveyKey: process.env.NEXT_PUBLIC_SIBILANCE_SURVEY_KEY!,
}, {
onComplete: (yaml) => {
console.log('Survey completed!', yaml);
setResults(yaml);
// Submit to backend
fetch('/api/survey-results', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ results: yaml })
});
},
onRecordInformation: (info) => {
console.log('Recorded:', info.field, '=', info.value);
},
onError: (error) => {
console.error('Survey error:', error);
}
});
return (
<div className="app">
<header>
<h1>My Website</h1>
{voiceState.isConnected && (
<div className="voice-status">
{voiceState.isUserSpeaking && '🎤 Listening...'}
{voiceState.isAIThinking && '🤔 Thinking...'}
{voiceState.isAISpeaking && '🔊 Speaking...'}
</div>
)}
</header>
<main>
{surveyState.isActive && (
<div className="survey-progress">
<p>Survey in progress...</p>
<p>Current step: {surveyState.currentStepId}</p>
<p>Collected: {surveyState.collectedInfo.length} items</p>
</div>
)}
{surveyState.isComplete && (
<div className="survey-complete">
<h2>Survey Completed!</h2>
<pre>{JSON.stringify(results, null, 2)}</pre>
</div>
)}
<YourContent />
</main>
{/* Floating microphone button */}
<FloatingMicButton
isConnected={voiceState.isConnected}
onClick={toggleSession}
position="bottom-right"
/>
</div>
);
}
export default App;TypeScript Support
Full TypeScript support with type definitions:
tsx
import type {
SibilanceConfig,
SurveyCallbacks,
VoiceSessionState,
SurveyState
} from '@sibilance.is/client/react';
// Typed component
const MyComponent: React.FC = () => {
const config: SibilanceConfig = {
surveyKey: 'sibilance_your_key_here'
};
const callbacks: SurveyCallbacks = {
onComplete: (yaml) => {
console.log('Completed:', yaml);
}
};
const { voiceState, surveyState } = useSibilance(config, callbacks);
return <div>{voiceState.isConnected && 'Connected'}</div>;
};Styling
Custom Styles
tsx
<FloatingMicButton
isConnected={voiceState.isConnected}
onClick={toggleSession}
style={{
'--sibilance-primary-color': '#007bff',
'--sibilance-background': '#ffffff',
'--sibilance-border-radius': '50%'
} as React.CSSProperties}
/>CSS Classes
tsx
<FloatingMicButton
isConnected={voiceState.isConnected}
onClick={toggleSession}
className="my-custom-button"
/>css
.my-custom-button {
/* Your custom styles */
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
}Related
- Getting Started - Basic setup guide
- Sibilance Client - Core client API
- Quick Start - Quick integration guide
- API Reference - React API documentation