Platform docs
Auth, users, webhooks & more
Info:
This is beta documentation for Stream Video React SDK v2. For the latest stable version, see the latest version (v1).

Upgrade to v2

v2 of the React SDK is in beta. This page tracks what you have to change when moving from v1. The client API is unchanged so far; the breaking changes to date are in the component layer, where the SDK is moving onto the design system, and in the translation layer, which moved to the runtime shared with Stream Chat.

Install the beta

v2 publishes to the beta npm tag. v1 keeps latest, so an unpinned install stays on v1.

yarn add @stream-io/video-react-sdk@beta

Quick migration checklist

  1. Install the beta and build. Client, call and state APIs need no changes.
  2. Replace TextButton with Button, and IconButton's enabled prop with active.
  3. Replace variant="success", variant="danger" and variant="active".
  4. Search your CSS for the removed str-video__ button classes and the eight --str-video__composite-button__button-group* variables.
  5. Re-check any spacing you derived from --str-video__spacing-*: the scale shifted.
  6. Look at your call controls on screen. Sizing changed even where your code did not.
  7. If you translated the SDK, re-key your dictionaries and rename translationsOverrides to translations. This one fails silently - see below.
  8. Replace <CallStats />. It is no longer exported - build the panel you need from useCallStatsReport().
  9. Change StreamTheme's theme from a class name to "light" or "dark", and move embedded CSS variable overrides from theme to style. Both fail silently - see below.

The button family is now one component

Before v2 there were three unrelated components: .str-video__button was a full-width CTA, IconButton rendered a bare padded icon with no background or state, and only CompositeButton produced the round call-control pill.

They are now one token-driven primitive. .str-video__button carries the pill, IconButton is its icon-only shape, and CompositeButton composes it into a call control with an optional caption and split menu. Button is exported for the first time.

Renamed and removed

Removed Replacement
TextButton Button
IconButtonWithMenuProps CompositeButtonProps
IconButton prop enabled active
variant="success" | "danger" | "active" "destructive", or the active prop

variant now maps to the design system's Style and appearance to its Type. active renders as aria-pressed, so a selected control is exposed to assistive technology rather than only styled.

Removed CSS classes

str-video__text-button, str-video__button__icon, str-video__call-controls__button*, str-video__composite-button__button* and str-video__menu-toggle-button* are gone. They are replaced by str-video__button--* and str-video__composite-button__{group,action,caret}.

Removed theming variables

The eight --str-video__composite-button__button-group* hooks are gone. Buttons are themed through the design tokens now.

Spacing was re-based

--str-video__spacing-* keep their names but every step shifted:

Token v1 v2
xs 6px 8px
sm 8px 12px
md 12px 16px
lg 16px 20px
xl 20px 24px

If you used these tokens for your own layout, it moves with them. Icon-only button insets also changed (at lg, from 8px to 16px), so a button sized around its own padding is now a different size.

Translations moved to a shared runtime

The SDK now uses @stream-io/i18n, the translation runtime shared with Stream Chat, and translation keys are namespaced identifiers instead of the English text:

t("Mute all"); // v1
t("participantList.muteAll.label", "Mute all"); // v2

The second argument is the English copy, written at the call site. That is why the SDK no longer ships an en.json or a translations export: a key missing from your dictionary renders that inline English rather than a raw key.

If you never touched i18n, there is nothing to do. English is unchanged - every string renders exactly as it did in v1.

If you did translate the SDK

Warning:

Re-keying is not optional, and it fails quietly. An old key never matches, so your override silently stops applying and the SDK's English renders instead - no error, no warning, nothing in the console. Type your dictionaries as TranslationDictionary to turn that into a compile error.

Removed Replacement
translationsOverrides translations - registers over the defaults instead of replacing
fallbackLanguage removed - use i18nextConfigOverrides: { fallbackLng }
StreamI18n Streami18n - different class, different options
StreamI18nProvider removed - StreamVideo mounts the translation context
TranslationsMap Record<string, LooseTranslationDictionary>
TranslationLanguage, TranslatorFunction removed - use string and StreamTFunction
the translations export, en.json removed - English is inline at each call site
useI18n().i18n removed - useI18n() returns { t, tDateTimeParser }

The old-to-new key mapping is published as i18n-2.0-key-map.json in the SDK repository. Most rows are a straight rename; a handful are not, and those carry a note explaining what to do.

Note that translationsOverrides replaced the SDK's dictionary in v1 rather than merging with it, so supplying one German string dropped the rest. If you worked around that by spreading the SDK's translations.en back into yours, delete the spread - translations merges, and a partial dictionary is safe.

The i18n guide covers the new API in full.

CallStats was removed

The prebuilt CallStats panel is no longer part of the SDK. The data behind it is unchanged: useCallStatsReport() still emits a full report every two seconds, and call.setStatsReportingIntervalInMs() still controls the cadence.

Removed Replacement
CallStats Your own panel, built on useCallStatsReport()

The Call Statistics recipe rebuilds the panel v1 shipped - the same stats, the same latency and jitter thresholds, and the bitrate derivation the component did internally - so a v1 panel can be restored by copying it in.

CallStatsButton is unaffected. It toggles whichever panel you render; it no longer has a panel of its own to toggle.

theme is now "light" or "dark"

StreamTheme's theme prop used to take a CSS class name, with "str-video__theme-dark" as the default. It now takes "light" or "dark", still defaulting to dark, and renders str-video__theme-light or str-video__theme-dark itself.

EmbeddedCall and EmbeddedLivestream take the same "light" or "dark" value in their theme prop. The CSS variable overrides that theme used to accept move to a new style prop.

v1 v2
<StreamTheme theme="str-video__theme-dark"> <StreamTheme theme="dark">, or omit it
<StreamTheme theme=""> (light) <StreamTheme theme="light">
<EmbeddedCall theme={{ "--str-video__…": "…" }} /> <EmbeddedCall style={{ "--str-video__…": "…" }} />
- <EmbeddedCall theme="light" />

A class name passed to theme no longer matches any theme: it renders as str-video__theme-<your value>, so the UI silently falls back to the light tokens. A CSS variable object passed to the embedded theme is ignored in the same way. TypeScript flags both; plain JavaScript does not.

The Theme page covers the new props.

What to expect during the beta

The design-token migration is proceeding component by component, so more changes of this shape are coming. Treat this page as the running list and re-read it when you bump; each entry will name the version it landed in and the change you have to make.

If you hit something that behaves differently and is not listed here, that is worth reporting: an unlisted break is a bug in this page as much as in the SDK.

Staying on v1

v1 is maintained on its own release line and stays on the latest tag. If you are not ready to move, pin @stream-io/video-react-sdk@latest and switch this page to v1 with the version picker above.

Add Chat to my app: getstream.io/SKILL.md

The fastest way to build with Stream. Start a new project or improve an existing one. Full CLI and documentation integration out of the box.


Ask your agent:

/stream Build me a Social App with Feeds and Moderation.
/stream Any livestream calls running?
/stream Video React v2: <Your Question>