React
The @saytv/chat-react package provides a typed React component and hook for integrating the chat widget.
Installation
npm install @saytv/chat-reactPeer dependencies: React 17+ and react-dom 17+.
Basic Usage
import { SayTVChat } from '@saytv/chat-react';
function App() {
return (
<SayTVChat
appId="your-app-id"
theme="light"
height={700}
width="100%"
/>
);
}With External Auth
import { SayTVChat } from '@saytv/chat-react';
function App() {
const [token, setToken] = useState<string | undefined>();
useEffect(() => {
// Fetch your user's JWT token
fetchUserToken().then(setToken);
}, []);
return (
<SayTVChat
appId="your-app-id"
authToken={token}
builtInAuth={false}
theme="light"
height={700}
width="100%"
/>
);
}Props
| Prop | Type | Default | Description |
|---|---|---|---|
appId | string | - | App identifier (resolves API URL automatically) |
env | 'production' | 'staging' | 'production' | API environment |
apiUrl | string | - | Direct API base URL (overrides appId/env) |
authToken | string | - | JWT access token for external auth |
builtInAuth | boolean | true | Show built-in login/register UI |
fanzone | boolean | false | Enable the Fanzone feature |
height | number | 850 | Widget height in pixels |
width | string | '450px' | Widget width (any CSS value) |
mode | 'page-chat' | - | Enables page chat mode |
pageId | string | window.location.href | Unique identifier for page chat |
pageName | string | document.title | Display name for page chat |
customTabUrl | string | - | URL loaded in a custom tab iframe |
customTabLabel | string | - | Label shown on the custom tab |
customTabIcon | string | - | Icon name for the custom tab |
theme | 'light' | 'dark' | 'light' | Color theme |
locale | string | 'en' | BCP-47 UI language; RTL auto |
translations | Record<string, Record<string, string>> | - | Catalogs keyed by locale, merged over English |
translationsUrl | string | - | URL of a hosted flat JSON catalog to fetch and apply for the active locale |
className | string | - | CSS class on wrapper <div> |
style | CSSProperties | - | Inline styles on wrapper <div> |
onReady | (e: CustomEvent) => void | - | Widget initialized |
onUserLogin | (e: CustomEvent) => void | - | Fired on successful login |
onUserLogout | (e: CustomEvent) => void | - | Fired on logout |
onMessageSent | (e: CustomEvent) => void | - | Fired when user sends a message |
onMessageReceived | (e: CustomEvent) => void | - | New message from another user |
onNavigation | (e: CustomEvent) => void | - | Page changed within widget |
onEpisodeChanged | (e: CustomEvent) => void | - | User selected an episode |
onRoomJoined | (e: CustomEvent) => void | - | User entered a chat room |
onThemeChanged | (e: CustomEvent) => void | - | Theme switched |
onPageChatReady | (e: CustomEvent) => void | - | Page chat episode is created or reconnected |
onError | (e: CustomEvent) => void | - | Fired on SDK errors |
All props are optional and reactive - updating a prop updates the underlying <saytv-chat> element.
useSayTVChat Hook
The useSayTVChat hook provides imperative access to the widget:
import { SayTVChat, useSayTVChat } from '@saytv/chat-react';
function App() {
const { chatRef, getElement, setToken, setTheme } = useSayTVChat();
return (
<>
<SayTVChat
ref={chatRef}
appId="your-app-id"
theme="light"
height={700}
width="100%"
/>
<button onClick={() => setTheme('dark')}>Dark Mode</button>
<button onClick={() => setToken(newToken)}>Update Token</button>
</>
);
}Hook Return Values
| Property | Type | Description |
|---|---|---|
chatRef | RefObject<SayTVChatRef> | Pass to <SayTVChat ref={chatRef}> |
getElement() | () => HTMLElement | null | Returns the underlying <saytv-chat> element |
setToken(token) | (token: string) => void | Updates the auth-token attribute |
setTheme(theme) | (theme: 'light' | 'dark') => void | Switches the color theme |
Event Handling
function App() {
return (
<SayTVChat
appId="your-app-id"
onReady={() => console.log('Widget ready')}
onUserLogin={(e) => console.log('Logged in:', e.detail.user)}
onMessageSent={(e) => console.log('Sent:', e.detail.message)}
onMessageReceived={(e) => console.log('Received:', e.detail.message)}
onEpisodeChanged={(e) => console.log('Episode:', e.detail.episode)}
onError={(e) => console.error('Error:', e.detail.error)}
/>
);
}Custom Theming
Pass CSS custom properties via the style prop:
<SayTVChat
appId="your-app-id"
theme="light"
style={{
'--stv-color-primary': '#4f46e5',
'--stv-color-accent': '#10b981',
'--stv-border-radius-md': '12px',
} as React.CSSProperties}
/>See Theming for all available CSS variables.
Localization
Set the UI language with locale and supply your own translation catalogs via translations. Catalogs are keyed by locale and merged over the built-in English, so untranslated keys fall back to English. RTL languages lay out automatically.
<SayTVChat
appId="your-app-id"
locale="ar"
translations={{
ar: {
'auth.login.title': 'مرحبا بعودتك',
'chat.input.placeholder': 'اكتب رسالة…',
},
}}
/>Alternatively, point translationsUrl at a hosted flat JSON catalog and the widget fetches and registers it for the active locale, no object needed. A failed fetch falls back to English.
<SayTVChat
appId="your-app-id"
locale="ar"
translationsUrl="https://your-cdn.com/locales/ar.json"
/>See Localization for the full guide and available keys.
TypeScript
All types are exported from the package:
import type { SayTVChatProps, SayTVChatRef } from '@saytv/chat-react';
import type { UseSayTVChatReturn } from '@saytv/chat-react';