Skip to content

Changelog

What changed in each release of the SayTV Chat SDK, and what — if anything — you need to do about it.

Upgrading

With a package manager:

bash
npm install @saytv/chat-sdk@latest

From the CDN, by pinning the version in the URL:

html
<script type="module">
  import 'https://sdk.saytv.net/@saytv/chat-sdk@2.7.1/dist/widget.mjs';
</script>

Use @latest in place of a version number to stay on the newest release automatically. If you use the React or Vue packages, upgrade @saytv/chat-react or @saytv/chat-vue to the same version — they are released in lockstep with the SDK.

Every release below opens with the version to install and whether it asks anything of you.


2.7.1 — 24 August 2026

@saytv/chat-sdk@2.7.1 · No action needed.

One fix for iPhones. Worth taking if your audience chats from a phone.

Fixed

  • Typing on an iPhone zoomed the page in. Tapping the message box — or any other text field in the widget — made Safari magnify the whole page and leave it that way. The zoom is gone; the only visible change is that text typed on an iPhone shows slightly larger. Nothing changes on desktop or Android.

2.7.0 — 20 August 2026

@saytv/chat-sdk@2.7.0 · Read the first item if you have set your brand colours — polls change appearance. Otherwise no action needed.

Quizzes and polls now follow your brand, can be made readable on a light brand colour, and can each run in their own language. Worth taking if you run either.

Fixed

  • Polls ignored your brand colour. Quizzes followed your primary colour but polls were wired to a separate one, so they arrived in a generic blue whatever you configured. Polls now match your quizzes. This changes how polls look if you have set --stv-color-primary; set --stv-poll-bg to keep them deliberately different.

  • A translation file that failed to load said nothing. The widget fell back to English silently, which read as a missing translation rather than a failed download — your questions and messages appeared in the right language while the widget's own labels stayed English. It now reports the failure to the console and fires stv:error. See "When the UI stays in English" in the Localization docs.

  • Two widgets on one page reset each other. Closing one signed the viewer out of the other and reverted it to English. Each now cleans up only after itself.

Added

  • Quiz and poll panels are styleable. Sixteen variables cover the background, text, answer chips, result bars and submit button. The panels put text straight onto your brand colour and default to white, so set the text colour if your brand colour is light:

    html
    <saytv-chat style="--stv-color-primary: #2faee0; --stv-quiz-text: #0b2b3a"></saytv-chat>

    The Playground's Style → Quiz & Poll section previews both panels and warns when the text contrast is too low to read. Full list on the Theming page.

  • A quiz or poll can run in its own language. Its buttons and labels match the question, whatever language the chat is in — so a French poll reads "Envoyer la réponse" in an English chat, and an Arabic one lays itself out right-to-left. If you run one language, set it once for the whole client in the client panel; moderators can override it per interaction. The translation file for that language still has to be loaded. Needs the matching SayTV platform update, which ships alongside this release.


2.6.0 — 17 August 2026

@saytv/chat-sdk@2.6.0 · No action needed. Nothing changes unless you set one of the new attributes below.

Five new attributes for hiding parts of the widget you have not launched, and a set of fixes for the emoji and GIF panels on phones. Worth taking if you embed on mobile, or if your audience has no loyalty programme.

Added

  • Switch off the parts of the widget you have not launched yet. If your audience has no loyalty programme, the profile screen was still offering badges, a leaderboard and two stores, and every name in the chat opened a stranger's profile. Five new attributes turn those off one at a time, so the widget shows only what you can back:

    AttributeWhat it removes
    hide-badgesThe Badges card and its page
    hide-leaderboardThe Leaderboard card and its page
    hide-emoji-storeThe Emojis card and the emoji store
    hide-avatar-storeThe Avatars card and the avatar store
    hide-user-profilesTapping a message author, or a name in the member list, to open their profile
    html
    <saytv-chat hide-badges="true" hide-leaderboard="true" hide-user-profiles="true"></saytv-chat>

    Each one works on its own, so setting one leaves the others alone. Viewers keep their own profile in every case — it is where they set their name and avatar. With hide-user-profiles, names and avatars still appear in the chat; they simply stop being links. You can change any of these at runtime and the widget follows immediately, including when someone is already sitting on a page you have just switched off.

    In React and Vue they are props in the usual camelCase — hideBadges, hideLeaderboard, hideEmojiStore, hideAvatarStore, hideUserProfiles — and take a boolean:

    jsx
    <SayTVChat hideBadges hideLeaderboard hideUserProfiles />

Fixed

  • The emoji and GIF panels no longer swallow the whole chat on a phone. Both opened at a fixed height that, in a short embed, covered every message — the conversation simply vanished, and the only way back was a small grey × that people did not find. The panels now take at most 45% of the widget, so a strip of chat stays visible behind them and it is obvious what closing will return you to. Four ways back now, instead of one: the ×, tapping the chat behind the panel, the emoji or GIF button that opened it, and the Escape key.

  • The × on both panels is now a proper touch target. It was a 16px icon in a 28px box, below the size a thumb can reliably hit, and in a light grey that read as decoration. It is now full-contrast and meets the 44px minimum, without the panel header growing.

  • Opening the GIF panel on a phone no longer throws the keyboard up over it. The search box took focus the moment the panel opened, so the on-screen keyboard covered the GIFs it was there to show. On touch devices the keyboard now waits until you tap the search box. On a mouse or trackpad the field still focuses immediately, as before.


2.5.4 — 17 August 2026

@saytv/chat-sdk@2.5.4 · No action needed.

Quick reactions now reach the rest of the chat. Worth taking if your viewers use the reaction buttons above the message box.

Fixed

  • Quick reactions were only ever seen by the person who tapped them. The reaction floated up their own screen straight away, so it looked like it was working — but nobody else watching ever saw it. This affected episode chats and hashtag rooms alike, and it had been the case since quick reactions shipped. Everyone in the chat now sees them.

  • A failed request could show up as a redirect instead of an error. If you were tracing a problem in your browser's network tab, a request the widget got wrong appeared as a redirect back to your own page rather than a readable message saying what was wrong. That made widget problems much harder to diagnose than they needed to be — and it is why the issue above went unnoticed for so long. Errors now come back as errors, across every request the widget makes.


2.5.3 — 13 August 2026

@saytv/chat-sdk@2.5.3 · No action needed. Several of these fixes also need the matching SayTV platform update, which ships alongside this release — nothing for you to configure.

Quiz and poll voting fixes. If your viewers use quizzes or polls, this is worth taking.

Fixed

  • A vote could be counted for the wrong answer. A viewer tapped one option and the widget credited a different one — and then showed the tick next to the answer they hadn't chosen. It got more likely the more people voted, and it affected both quizzes and polls. Votes now always land on the option the viewer actually picked.

  • Vote counts now move as other people vote. On both quizzes and polls, the result bars only ever updated for the person who had just voted; everyone else sat on the numbers from the moment they answered. They now update live for everyone watching.

  • Poll percentages were wrong, not just stale. Where a poll's bars did move, they were recalculated against the new total using each option's old count — so an option with no votes at all could show 50%. The numbers are now the real ones.

  • The widget remembers which answer a viewer chose. After a page reload, or coming back to a quiz they had already answered, the tick next to their answer was missing. It stays put now.

  • One viewer voting no longer locks the quiz for everybody else. The widget could mistake somebody else's vote for the viewer's own and close voting early for people who hadn't answered yet.

  • A phantom extra answer no longer appears. Quizzes could show a stray extra option labelled 1 alongside the real answers, and viewers could vote for it.

  • Answers no longer reshuffle mid-quiz. The order of the options could change under the viewer while a quiz was running.

Types

If you only use the <saytv-chat> element, its attributes and events, nothing changes for you.

TypeChange
QuizNew optional voted_option_key — the position (14) of the answer the viewer chose. Use this to find their answer in Quiz.options on a regular quiz; voted_option_id still holds the underlying record id and remains the one to match on for MVP quizzes.

2.5.2 — 13 August 2026

@saytv/chat-sdk@2.5.2 · No action needed, unless you ship your own translation catalog — see below.

Stability fixes for the Friends section.

Fixed

  • Opening Friends could lock up the whole widget — no taps, no navigation — until the visitor reloaded the page. It happened when the widget's session had expired, or when the visitor wasn't fully signed in. The widget now recovers on its own: with the built-in login it returns to the sign-in screen, and with auth-token or guest mode it quietly starts a fresh session and carries on.

  • A missing username, or a friend request from a deleted account, no longer breaks the screen showing it. Both now display normally. And if anything unexpected does still go wrong, the widget shows "Something went wrong" with a Retry button instead of freezing — using the common.error and common.retry strings your catalog already covers.

  • The Friends and Requests lists no longer come up empty right after the page loads. They used to stay blank until the visitor switched tabs and back; they now fill in as soon as sign-in completes.

Changed

  • Guests no longer see the Friends tab. Friends need a signed-in account, so for anonymous visitors the tab led nowhere useful. It is now hidden in guest mode, and a guest who reaches the screen another way sees "Sign in to add friends" rather than errors.

    If you ship your own translation catalog, two new keys cover that prompt: friends.guestTitle ("Sign in to add friends") and friends.guestDescription ("You're browsing as a guest. Sign in to connect with other fans."). The downloadable reference catalogs — English, Spanish, French, Arabic — already include them, and anything you don't translate falls back to English as usual.

2.5.1 — 12 August 2026

@saytv/chat-sdk@2.5.1 · Action needed if you ship your own translation catalog, or if your page binds single-key keyboard shortcuts.

Changed

  • The GIF search box now reads "Search KLIPY". KLIPY, the provider behind the GIF picker, requires its brand name in the search placeholder, fully capitalized. The default English text changed from "Search GIFs…" to "Search KLIPY".

    If you ship your own translation catalog, keep KLIPY in that value. The key is unchanged (chat.gif.searchPlaceholder), so your catalog overrides the new default — which would put your integration outside KLIPY's attribution guidelines. The reference catalogs are already updated for you: "Buscar KLIPY", "Rechercher KLIPY", "البحث في KLIPY".

Fixed

  • Keyboard shortcuts on your page no longer fire while someone is typing in the chat. If your page binds single keys on document — space for play/pause, m for mute, f for fullscreen, as most video players do — those shortcuts ran on every keystroke typed into the widget. Space was the one visitors noticed: the page took it as a play/pause press and cancelled the keystroke, so "Hola Hola" came out as "HolaHola". The message box, GIF search, message search, quiz and username fields were all affected.

    What this changes for your page: printable keystrokes typed inside the widget no longer reach listeners on document or window. Escape, Tab, Enter and the arrow keys still do, so shortcuts built on those keep working.

    If your own handler needs to know whether a keystroke came from the chat, read event.composedPath()[0] rather than event.target. The widget renders in a shadow DOM, so event.target reports the <saytv-chat> element for anything typed inside it — which is why the usual "is the user typing in a field?" check does not catch it:

    js
    document.addEventListener('keydown', (event) => {
      const source = event.composedPath()[0];
      if (source.tagName === 'INPUT' || source.tagName === 'TEXTAREA' || source.isContentEditable) {
        return; // the user is typing - leave the keystroke alone
      }
      // your shortcut here
    });

    One case this does not cover: a handler registered in the capture phase (addEventListener('keydown', fn, true)) runs before the widget can stop the keystroke, so it still fires. Use the composedPath() guard above for those.

2.5.0 — 11 August 2026

@saytv/chat-sdk@2.5.0 · No action needed — but if you use the React package, upgrade it too. See below.

New

  • hide-avatar removes every entry point to the built-in avatar picker: the button in the chat header, the one that floats in the corner when the header and tab bar are both hidden, and the avatar on the profile screen. Meant for sites that own their users' avatars. Without it, an avatar a user picks in the widget is treated as deliberate and kept in place of the avatar-url you supply, so your own avatars stop applying to that user from then on. See the Sizing & Layout guide.
  • hide-guest-notice removes the read-only bar shown to guests in place of the message box ("You're browsing as a guest…") — for sites whose own UI already explains how to sign in. The bar is removed entirely rather than blanked, so no empty strip is left behind.

Both work on <saytv-chat> and <saytv-chat-bubble>, can be changed at runtime, and are available as the hideAvatar and hideGuestNotice props in the React and Vue packages.

Fixed

  • React: the widget could start up with no API URL and load nothing. <SayTVChat> applied its props after adding the element to the page, but the widget reads its whole configuration the moment it arrives there — so apiUrl, appId, env, mode, pageId, pageName, builtInAuth, avatarUrl and the custom-tab props were never picked up, and every request went to your own page's origin instead. Props are now applied first. Upgrade @saytv/chat-react to 2.5.0. Vue was not affected.

2.4.6 — 7 August 2026

@saytv/chat-sdk@2.4.6 · No action needed.

Fixes for hidden-header and hidden-tab-bar layouts, and for what guests are offered.

Fixed

  • No way back when the header is hidden. With hide-header="true", opening a hashtag room from a message, or a member's profile from their name, left visitors stuck there — the header carried the only back button. A floating back button now appears in the top corner whenever there is somewhere to return to, and hides itself again once you are back at the top level. In page chat it never appears on the chat screen itself, which is already the top level. It needs no new attribute, and can be restyled with the new --stv-floating-nav-* variables. See the Sizing & Layout guide.
  • The avatar button vanished when the header and tab bar were both hidden, leaving no way to change an avatar. It now floats in the opposite corner from the back button on chat screens.
  • Guests were offered friend and moderation actions they could not use. Add Friend, Unfriend, Block and Report appeared on other members' profiles for anonymous visitors, and every one was rejected. They now show only to signed-in users, matching how they are already hidden on your own profile.
  • Guests were offered an avatar button they could not use. The "change avatar" button appeared to anonymous visitors whenever the tab bar was hidden, and picking an avatar was always rejected. It now shows only to signed-in users. The back button is unchanged — guests can still open rooms and profiles, so they still need a way back.
  • The chat bubble ignored hide-header, hide-footer and avatar-url. Setting them on <saytv-chat-bubble> did nothing. All three now work there, and can be changed at runtime like the bubble's other pass-through attributes. See Bubble Attributes.
  • stv:navigation did not fire when someone went back. Only forward navigation was reported, so unread badges, analytics and anything else listening for page changes silently missed every back step. Going back now fires the event too, with page set to the screen being returned to.

2.4.5 — 5 August 2026

@saytv/chat-sdk@2.4.5 · No action needed.

Changed

  • YouTube videos now play inside the chat. Clicking a YouTube preview used to leave for youtube.com in a new tab; it now plays the video right in the message. Clicking the video's title still opens it on YouTube. This costs nothing on page load — the player is only created once someone presses play.

Fixed

  • Long unbroken text in a quiz ran off the edge of the card. A quiz title or answer written as one long unbroken string was clipped at the card's edge, and the vote percentages beside the answers were pushed out of view entirely. The text now wraps inside the card, and the percentages always stay visible.
  • YouTube messages from older SayTV apps read "video preview" / "video url". Messages posted from older clients carry that placeholder text instead of the video's details. The widget now recognises the placeholders and fetches the video's real title and channel name from YouTube instead. YouTube thumbnails also no longer show black bars above and below the picture.

2.4.4 — 4 August 2026

@saytv/chat-sdk@2.4.4 · No action needed.

Fixed

  • Quiz results read 0% for every answer the moment you voted. Submitting an answer switched the quiz to its results view, but the percentages shown were the ones from before your vote was counted — so on a quiz you were first to answer, the option you had just picked read 0% instead of 100%. Reopening the quiz showed the right figures, so this only affected the moment right after voting. Results now count your answer immediately.
  • Fanzone cards showed a literal "{count} episodes" under the fanzone name. The episode count is not part of what the API returns for a fanzone, so the line now appears only when a count is actually available.

2.4.3 — 4 August 2026

@saytv/chat-sdk@2.4.3 · Action needed only if your TypeScript code reads User, Badge or Episode objects directly.

Fixed

  • Experience points now show the real figure. A user's own profile read "0 EP" however many points they had, and on another member's profile and in the friends lists the text came out as a literal "{count} EP".
  • Opening the emoji panel while the GIF panel is up now works. The emoji button appeared to do nothing — the panel was opening behind the GIF panel, and you had to close the GIF panel by hand first. Either button now replaces the other, and the quick-reaction bar steps out of the way while a panel is open.
  • The emoji panel now opens the same way the GIF panel does, without its own slide-in animation or drop shadow. In bubble mode it also keeps its top border, which it previously lost.
  • Badge progress counts the whole set. The profile tile and the badges screen read "3/3" whatever the real total was, because only earned badges were loaded. They now read e.g. "3/54", with the badges still to earn shown greyed out beside the earned ones. Badges beyond the first 28 were not loaded at all, so some never appeared.
  • Your own profile no longer offers Add Friend, Unfriend, Block and Report against yourself. That screen is reachable from your own name in chat, the members list and the leaderboard.
  • Episode cards no longer show a message count of 0. The API sends no comment count, so the figure could never be anything else. The count of people in the chat is unaffected.

Changed

Three fields were renamed or removed to match what the API returns. If you only use the <saytv-chat> element, its attributes and events, nothing changes for you — this affects TypeScript code reading these objects directly.

TypeBeforeNow
Userep_balancetotal_experience_points
Badgeimage_urlimage
Episodecomments_countremoved — not returned by the API

As in 2.4.1, the old names were never populated, so moving to the names on the right is what makes these values appear.

New

  • getLockedBadges() and getBadgeCollection() — the badges a user has yet to earn, and the full set in one call.

Also shipping with this release, on the SayTV API: guest sessions and staff accounts no longer appear on the leaderboard (a guest had reached rank 1), nor in the chat member list and its @-mention suggestions. Both are server-side and take effect once the API is deployed — no SDK upgrade required.

2.4.2 — 4 August 2026

@saytv/chat-sdk@2.4.2 · Action needed only if you load a translation catalog from sdk.saytv.net.

Fixed

  • The downloadable translation catalogs showed a literal {time}. 2.4.1 changed the badges.earned string to read simply "Earned", but the catalogs served from the CDN and linked with translations-url were not regenerated — so a badge's detail panel read "Earned {time}" in English, and the equivalent in Arabic, Spanish and French. Point translations-url at @latest or @2.4.2 to pick up the corrected text. The catalog built into the package was already correct, so this only affected setups using an external catalog.

2.4.1 — 4 August 2026

@saytv/chat-sdk@2.4.1 · Action needed if your TypeScript code reads User, Badge or Avatar objects directly, or if you ship your own translation catalog.

Avatars, badges and the emoji picker were all showing placeholder or empty states instead of real content. This release fixes them.

Fixed

  • Avatars now appear. Every avatar in the widget rendered as a blank circle: the onboarding Choose a Username chooser, the avatar picker on the profile, and the avatar store. Picking one also silently failed to save, so users were stuck with the default. All three now show the real artwork, and selecting one takes effect immediately.
  • The avatar store now lists its avatars instead of showing "no avatars available", and unlocking one with SayBucks now works.
  • Profile pictures now show up throughout the widget. The profile ring, the chat-header button, the members sidebar, @-mention suggestions and the friends lists were all falling back to the user's initial even when they had an avatar set. Chat messages were unaffected.
  • Earned badges are marked as earned. Badges the user had already unlocked were shown dimmed and without their tick, and the counter read 0/2 instead of 2/2.
  • The emoji picker opens reliably. An unexpected response could stop it opening at all. It now opens and shows an empty category rather than nothing.
  • avatar-url no longer re-uploads the same image on every page load.

Changed

Four data shapes now match what the API returns. If you only use the <saytv-chat> element, its attributes and events, nothing changes for you — this affects TypeScript code reading these objects directly.

TypeBeforeNow
Useravatar_urlavatar (already the full URL)
Badgeimage_urlimage
Badgeid, earned_atremoved — not returned by the API
Avatarid, image_url, is_activestore_item_id, image, purchased

The old names were never populated — reading them always gave undefined — so moving to the names on the right is what makes these values appear.

If you ship your own translation catalog: badges.earned no longer takes a {time} placeholder and now reads simply "Earned", because the API exposes no earned-on date. Update that key in your catalog. If you load your catalog from the CDN rather than shipping it yourself, see 2.4.2.

New

  • getLockedBadges() — the badges a user has not earned yet, to complement the existing earned-badge call.

Emoji packs not appearing? An emoji pack is only served to the widget once it has a store item attached (set its SayBucks price to 0 to make it free) and is attached to at least one emoji pack category. A pack missing either is filtered out server-side, so its images never reach the widget no matter how many you upload. Both are set on the pack in the admin panel.

2.4.0 — 31 July 2026

@saytv/chat-sdk@2.4.0 · Check before you rely on guest mode — it needs read-only access enabled for your tenant. See below.

New

  • Guest mode (read-only browsing). With built-in-auth="false" and no auth-token, the widget now opens an anonymous session on start-up, so visitors can read the chat without signing in — previously a tokenless widget could not load any content at all. Guests can browse episodes, chat history, the leaderboard and reactions; the message box is replaced with a prompt to sign in. Sessions are anonymous and disposable, so you can set auth-token at any point to swap in a real user. See the Authentication guide.
  • setUsername(name) renames the signed-in user from your own UI. Available on <saytv-chat>, <saytv-chat-bubble>, and the useSayTVChat() hook in the React and Vue packages. It resolves with the updated user, or rejects with a 422 and a field-level reason when the name is taken, too short, or blocked by moderation. See Methods.

Changed

  • A username claim in your JWT now renames the user on every re-authentication, not only when the account is first created — so issuing a token with a changed claim renames the user. If the claimed name already belongs to someone else, the rename is skipped and the user keeps their current name; authentication succeeds either way, so a name clash can never lock anyone out of chat. Use setUsername() when you need a definitive success or failure.

Fixed

  • @saytv/chat-react and @saytv/chat-vue now require a matching SDK version. They accepted ^2.0.8 or newer, which allowed a new wrapper to be installed against an SDK too old to provide the API it calls.
  • A failed background request no longer ends the session. Optional requests that return 401 — such as the GIF picker's recent list — are now ignored instead of logging the user out.
  • No more spurious 401 on first load — the widget no longer issues a request before its session is ready.
  • A failed GET no longer surfaces an unhandled promise rejection in the browser console.

Documentation

  • New Methods reference covering the JavaScript API on <saytv-chat>.
  • The Authentication guide now covers guest mode and how usernames map from JWT claims.
  • Arabic, Spanish and French catalogs updated with the new strings.

Before you rely on guest mode: it needs read-only access enabled for your tenant, so that guests are refused on write endpoints. This is on by default for new tenants — contact SayTV if you are unsure about yours.

2.3.0 — 29 July 2026

@saytv/chat-sdk@2.3.0 · No action needed — every new attribute and CSS variable is optional, and each defaults to the existing look.

New

  • Hide the header and tab bar. The new hide-header and hide-footer attributes let you embed a stripped-down chat without the top title bar and/or the bottom tab-bar navigation. Both can be toggled at runtime. See the Sizing & Layout guide.
  • Custom user avatar URL. The new avatar-url attribute sets the signed-in user's avatar from an image URL you provide — their photo from your own site, for instance. It is applied after authentication, and never overrides an avatar the user has chosen in the widget.
  • Avatar access without the tab bar. When the tab bar is hidden, an avatar button now appears in the chat header so users can still change their avatar. The picker is also available app-wide now, not just on the Profile screen, and selecting an avatar updates it everywhere immediately — including on your own chat messages.
  • Choose an avatar during onboarding. The first-run username prompt now also offers a library avatar chooser, shown only when avatars are available, so new users can set their name and picture in one step.
  • Custom icons. Override built-in icons with the new icons property on <saytv-chat>, or the icons prop in the React and Vue components. Supply a map of icon name → inline SVG string or image URL for back, search, users, send, emoji, chat, friends, fanzone, profile and close. Inline SVGs using currentColor are recolored to match their context. See the Custom Icons guide.
  • Header and tab bar colors. New CSS variables style the header (--stv-header-bg, --stv-header-text, --stv-header-icon) and the bottom tab bar (--stv-footer-bg, --stv-footer-border, --stv-footer-text, --stv-footer-text-active, --stv-footer-icon, --stv-footer-icon-active, --stv-footer-indicator) independently of the brand color. See the Theming guide.
  • Per-message appearance. Every message row can now be styled with a background, hover background, corner radius and side margin (--stv-message-bg, --stv-message-bg-hover, --stv-message-border-radius, --stv-message-inline-margin) — enabling flat, banded or card-style message lists. See the Theming guide.
  • Moderator message highlighting. Moderator messages support the same appearance controls plus a customizable border. Set each border side independently (--stv-mod-border-top/right/bottom/left) or all at once with the --stv-mod-border shorthand, alongside --stv-mod-bg, --stv-mod-bg-hover, --stv-mod-border-radius and --stv-mod-inline-margin — each inheriting the matching --stv-message-* value by default. Moderators are also now correctly identified from the message data; previously the highlight was never applied.
  • Message spacing and message box size. New CSS variables tune the gap between message groups (--stv-message-gap), the gap within a group (--stv-message-gap-grouped), the row padding (--stv-message-padding), and the message box (--stv-input-min-height, --stv-input-max-height, --stv-input-padding, --stv-input-font-size). Consecutive messages from the same author now render as a single connected card — rounded only at the top of the first row and the bottom of the last — so backgrounds and borders read as one block. See the Sizing & Layout guide.

2.2.3 — 20 July 2026

@saytv/chat-sdk@2.2.3 · No action needed.

Changed

  • The members panel now shows the true member count in its badge, taken from the server total instead of counting only the rows loaded so far. It also shows a live "N online" indicator, and is now titled Members rather than "Active Users", to reflect that it lists everyone in the chat.

2.2.2 — 30 June 2026

@saytv/chat-sdk@2.2.2 · No action needed.

Changed

  • The widget is around 35% smaller over the CDN. The published ESM bundles (widget.mjs, bubble.mjs, …) are now minified — roughly 79 kB down to 51 kB gzipped. No API changes.

2.2.1 — 30 June 2026

@saytv/chat-sdk@2.2.1 · No action needed — documentation only.

Documentation

  • Localization (locale, translations, translations-url) is now documented in the React and Vue package READMEs, and in the configuration reference.

2.2.0 — 30 June 2026

@saytv/chat-sdk@2.2.0 · No action needed.

New

  • Localization (i18n). Set the interface language with the locale attribute — a BCP-47 tag such as es or ar. Right-to-left languages lay out automatically, and changing the locale switches the language instantly with no reload. Works on both <saytv-chat> and the <saytv-chat-bubble> launcher.
  • Bring your own translations. Supply a catalog with the translations-url attribute — point it at a hosted JSON file, no JavaScript required — or with the translations property. Any string you don't translate falls back to English automatically. The React and Vue components expose locale, translations and translationsUrl props.
  • Ready-made catalogs. English, Arabic (RTL), Spanish and French catalogs are hosted on the SDK CDN, ready to use as-is or to download and customize. See the Localization guide.

SayTV Chat SDK Documentation