Skip to content

React

The @saytv/chat-react package provides a typed React component and hook for integrating the chat widget.

Installation

bash
npm install @saytv/chat-react

Peer dependencies: React 17+ and react-dom 17+.

Basic Usage

tsx
import { SayTVChat } from '@saytv/chat-react';

function App() {
  return (
    <SayTVChat
      appId="your-app-id"
      theme="light"
      height={700}
      width="100%"
    />
  );
}

With External Auth

tsx
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

PropTypeDefaultDescription
appIdstring-App identifier (resolves API URL automatically)
env'production' | 'staging''production'API environment
apiUrlstring-Direct API base URL (overrides appId/env)
authTokenstring-JWT access token for external auth
builtInAuthbooleantrueShow built-in login/register UI
fanzonebooleanfalseEnable the Fanzone feature
heightnumber850Widget height in pixels
widthstring'450px'Widget width (any CSS value)
mode'page-chat'-Enables page chat mode
pageIdstringwindow.location.hrefUnique identifier for page chat
pageNamestringdocument.titleDisplay name for page chat
customTabUrlstring-URL loaded in a custom tab iframe
customTabLabelstring-Label shown on the custom tab
customTabIconstring-Icon name for the custom tab
hideHeaderbooleanfalseHide the top title bar on every page
hideFooterbooleanfalseHide the bottom tab-bar navigation
hideAvatarbooleanfalseHide every entry point to the built-in avatar picker. Use when your app owns the user's avatar
hideGuestNoticebooleanfalseHide the read-only bar shown to guests in place of the composer
hideBadgesbooleanfalseHide the Badges card on the profile screen and its page
hideLeaderboardbooleanfalseHide the Leaderboard card on the profile screen and its page
hideEmojiStorebooleanfalseHide the Emojis card and the emoji store page. The emoji picker in the composer is unaffected
hideAvatarStorebooleanfalseHide the Avatars card and the avatar store page
hideUserProfilesbooleanfalseStop message authors and member-list names linking to that person's profile. Names and avatars still show; they stop being tappable. The signed-in user's own profile is unaffected
avatarUrlstring-Image URL applied as the signed-in user's avatar
theme'light' | 'dark''light'Color theme
localestring'en'BCP-47 UI language; RTL auto
translationsRecord<string, Record<string, string>>-Catalogs keyed by locale, merged over English
translationsUrlstring-URL of a hosted flat JSON catalog to fetch and apply for the active locale
classNamestring-CSS class on wrapper <div>
styleCSSProperties-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:

tsx
import { SayTVChat, useSayTVChat } from '@saytv/chat-react';

function App() {
  const { chatRef, getElement, setToken, setTheme, setUsername } = 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

PropertyTypeDescription
chatRefRefObject<SayTVChatRef>Pass to <SayTVChat ref={chatRef}>
getElement()() => HTMLElement | nullReturns the underlying <saytv-chat> element
setToken(token)(token: string) => voidUpdates the auth-token attribute
setTheme(theme)(theme: 'light' | 'dark') => voidSwitches the color theme
setUsername(name)(name: string) => Promise<User>Renames the signed-in user. Rejects with a 422 and errors.username when the name is taken, too short, or blocked by moderation. See Methods

Event Handling

tsx
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:

tsx
<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.

tsx
<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.

tsx
<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:

ts
import type { SayTVChatProps, SayTVChatRef } from '@saytv/chat-react';
import type { UseSayTVChatReturn } from '@saytv/chat-react';

SayTV Chat SDK Documentation