Repository: Azure/communication-ui-library
Pull request #5711: Promote together mode to stable
Author: login: cn0151
Labels: name: breaking-change
Created: 2025-03-14T17:54:13Z | Merged: 2025-03-18T01:00:38Z

# What
<!--- Describe your changes. -->

# Why
<!--- What problem does this change solve? -->
<!--- Provide a link if you are addressing an open issue. -->

# How Tested
<!--- How did you test your change. What tests have you added. -->

# Process & policy checklist
<!--- Review the list and check the boxes that apply. -->

- [ ] I have updated the project documentation to reflect my changes if necessary.
- [ ] I have read the [CONTRIBUTING](https://github.com/Azure/communication-ui-library/blob/main/CONTRIBUTING.md) documentation.

**Is this a breaking change?**

- [ ] This change causes current functionality to break.
<!--- If yes, describe the impact. -->


Diff:
diff --git a/change-beta/@azure-communication-react-0bc61add-56be-450e-b76c-7055ee2b919d.json b/change-beta/@azure-communication-react-0bc61add-56be-450e-b76c-7055ee2b919d.json
new file mode 100644
index 00000000000..fc178df7d84
--- /dev/null
+++ b/change-beta/@azure-communication-react-0bc61add-56be-450e-b76c-7055ee2b919d.json
@@ -0,0 +1,9 @@
+{
+  "type": "prerelease",
+  "area": "feature",
+  "workstream": "together-mode",
+  "comment": "We are excited to announce that the Azure Communication Services Web UI Library now supports Together Mode in Teams interop scenarios. Together Mode is a feature that creates a virtual shared space for meeting participants. By using AI segmentation technology, it places participants in a common background, such as a conference room or auditorium, making it look like everyone is sitting together. This mode is designed to make meetings feel more engaging and reduce virtual meeting fatigue. It can help improve participants' sense of connection and collaboration by mimicking the experience of being in the same physical location. Developers can use this functionality today through our composites (e.g CallComposite, CallWithChatComposite) as well as through components (e.g VideoGallery). Participants receive together Mode in Teams Interop Meetings, change views to and from Together mode and view reactions and raised hands in the Together mode view ",
+  "packageName": "@azure/communication-react",
+  "email": "nwankwojustin93@gmail.com",
+  "dependentChangeType": "patch"
+}
diff --git a/change-beta/@azure-communication-react-7fea4da2-61eb-41c5-9733-48ea5e25a3a3.json b/change-beta/@azure-communication-react-7fea4da2-61eb-41c5-9733-48ea5e25a3a3.json
new file mode 100644
index 00000000000..15963fabe87
--- /dev/null
+++ b/change-beta/@azure-communication-react-7fea4da2-61eb-41c5-9733-48ea5e25a3a3.json
@@ -0,0 +1,9 @@
+{
+  "type": "prerelease",
+  "area": "feature",
+  "workstream": "together-mode",
+  "comment": "Promote together mode to stable",
+  "packageName": "@azure/communication-react",
+  "email": "nwankwojustin93@gmail.com",
+  "dependentChangeType": "patch"
+}
diff --git a/change-beta/@azure-communication-react-86715e14-10d5-4a70-9e2e-048c3523cc0a.json b/change-beta/@azure-communication-react-86715e14-10d5-4a70-9e2e-048c3523cc0a.json
new file mode 100644
index 00000000000..15963fabe87
--- /dev/null
+++ b/change-beta/@azure-communication-react-86715e14-10d5-4a70-9e2e-048c3523cc0a.json
@@ -0,0 +1,9 @@
+{
+  "type": "prerelease",
+  "area": "feature",
+  "workstream": "together-mode",
+  "comment": "Promote together mode to stable",
+  "packageName": "@azure/communication-react",
+  "email": "nwankwojustin93@gmail.com",
+  "dependentChangeType": "patch"
+}
diff --git a/common/config/babel/features.js b/common/config/babel/features.js
index e209b34c72c..425057260db 100644
--- a/common/config/babel/features.js
+++ b/common/config/babel/features.js
@@ -68,15 +68,15 @@ module.exports = {
     // feature for tracking the callParticipantsLocator
     "call-participants-locator",
     // Feature for RTT
-    "rtt",
-    // Feature for together mode
-    "together-mode"
+    "rtt"
   ],
   stable: [
     // Demo feature. Used in live-documentation of conditional compilation.
     // Do not use in production code.
     "stabilizedDemo",
     // Feature for breakout rooms
-    "breakout-rooms"
+    "breakout-rooms",
+    // Feature for together mode
+    "together-mode"
   ]
 }
diff --git a/packages/calling-component-bindings/src/handlers/createCommonHandlers.ts b/packages/calling-component-bindings/src/handlers/createCommonHandlers.ts
index d015c2aa830..b8f203c48a2 100644
--- a/packages/calling-component-bindings/src/handlers/createCommonHandlers.ts
+++ b/packages/calling-component-bindings/src/handlers/createCommonHandlers.ts
@@ -114,30 +114,22 @@ export interface CommonCallingHandlers {
   /* @conditional-compile-remove(together-mode) */
   /**
    * Call back to create a view for together mode
-   *
-   * @beta
    */
   onCreateTogetherModeStreamView: (options?: TogetherModeStreamOptions) => Promise<void | TogetherModeStreamViewResult>;
 
   /* @conditional-compile-remove(together-mode) */
   /**
    * Call back to create a view for together mode
-   *
-   * @beta
    */
   onStartTogetherMode: () => Promise<void>;
   /* @conditional-compile-remove(together-mode) */
   /**
    * Call set together mode scene size
-   *
-   * @beta
    */
   onSetTogetherModeSceneSize: (width: number, height: number) => void;
   /* @conditional-compile-remove(together-mode) */
   /**
    * Call back to dispose together mode views
-   *
-   * @beta
    */
   onDisposeTogetherModeStreamView: () => Promise<void>;
   /**
diff --git a/packages/calling-stateful-client/src/CallClientState.ts b/packages/calling-stateful-client/src/CallClientState.ts
index b0f17162905..143809a30f2 100644
--- a/packages/calling-stateful-client/src/CallClientState.ts
+++ b/packages/calling-stateful-client/src/CallClientState.ts
@@ -336,7 +336,7 @@ export interface RaiseHandCallFeatureState {
 /* @conditional-compile-remove(together-mode) */
 /**
  * Represents the name of the call feature stream
- * @beta
+ * @public
  */
 export type CallFeatureStreamName = 'togetherMode';
 
@@ -344,27 +344,38 @@ export type CallFeatureStreamName = 'togetherMode';
 /**
  * State only version of {@link @azure/communication-calling#CallFeatureStream}.
  * Represents call feature stream state.
- * @beta
+ * @public
  */
 export interface CallFeatureStreamState extends RemoteVideoStreamState {
+  /**
+   * The name of the call feature stream.
+   */
   feature?: CallFeatureStreamName;
 }
 
 /* @conditional-compile-remove(together-mode) */
 /**
  * State only version of {@link @azure/communication-calling#TogetherModeSeatingMap}.
- * @beta
+ * @public
  *
  * Represents the seating position of a participant in Together Mode.
  */
 export interface TogetherModeSeatingPositionState {
-  /* The top left offset from the top of the together mode view.*/
+  /**
+   * The top left offset from the top of the together mode view.
+   */
   top: number;
-  /* The left offset position from the left of the together mode view. */
+  /**
+   * The left offset position from the left of the together mode view.
+   */
   left: number;
-  /*  The width of the seating area */
+  /**
+   * The width of the seating area
+   */
   width: number;
-  /* The height of the seating area. */
+  /**
+   * The height of the seating area.
+   */
   height: number;
 }
 
@@ -372,7 +383,7 @@ export interface TogetherModeSeatingPositionState {
 /**
  * Represents the seating positions of participants in Together Mode.
  *
- * @beta
+ * @public
  */
 export type TogetherModeParticipantSeatingState = Record<string, TogetherModeSeatingPositionState>;
 
@@ -380,9 +391,12 @@ export type TogetherModeParticipantSeatingState = Record<string, TogetherModeSea
 /**
  * Represents the streams in Together Mode.
  *
- * @beta
+ * @public
  */
 export interface TogetherModeStreamsState {
+  /**
+   * The main video stream in Together Mode.
+   */
   mainVideoStream?: CallFeatureStreamState;
 }
 
@@ -390,9 +404,12 @@ export interface TogetherModeStreamsState {
 /**
  * State only version of {@link @azure/communication-calling#TogetherModeCallFeature}. {@link StatefulCallClient}.
  * Represents the state of the Together Mode feature.
- * @beta
+ * @public
  */
 export interface TogetherModeCallFeatureState {
+  /**
+   * Flag indicating if Together Mode is active in the call
+   */
   isActive: boolean;
   /**
    * Proxy of {@link @azure/communication-calling#TogetherModeCallFeature.togetherModeStream}.
@@ -736,7 +753,6 @@ export interface CallState {
   /* @conditional-compile-remove(together-mode) */
   /**
    * Proxy of {@link @azure/communication-calling#TogetherModeCallFeature}.
-   * @beta
    */
   togetherMode: TogetherModeCallFeatureState;
   /**
diff --git a/packages/communication-react/review/beta/communication-react.api.md b/packages/communication-react/review/beta/communication-react.api.md
index 5260490ecbb..48925cccf4b 100644
--- a/packages/communication-react/review/beta/communication-react.api.md
+++ b/packages/communication-react/review/beta/communication-react.api.md
@@ -444,14 +444,12 @@ export interface CallAdapterCallOperations {
     addParticipant(participant: CommunicationUserIdentifier): Promise<void>;
     allowUnsupportedBrowserVersion(): void;
     createStreamView(remoteUserId?: string, options?: VideoStreamOptions): Promise<void | CreateVideoStreamViewResult>;
-    // @beta
     createTogetherModeStreamView(options?: TogetherModeStreamOptions): Promise<void | TogetherModeStreamViewResult>;
     disposeLocalVideoStreamView(): Promise<void>;
     disposeRemoteVideoStreamView(remoteUserId: string): Promise<void>;
     disposeScreenShareStreamView(remoteUserId: string): Promise<void>;
     // @deprecated
     disposeStreamView(remoteUserId?: string, options?: VideoStreamOptions): Promise<void>;
-    // @beta
     disposeTogetherModeStreamView(): Promise<void>;
     forbidAudio(userIds: string[]): Promise<void>;
     forbidOthersAudio(): Promise<void>;
@@ -477,14 +475,12 @@ export interface CallAdapterCallOperations {
     sendRealTimeText: (text: string, isFinalized: boolean) => Promise<void>;
     setCaptionLanguage(language: string): Promise<void>;
     setSpokenLanguage(language: string): Promise<void>;
-    // @beta
     setTogetherModeSceneSize(width: number, height: number): void;
     startCamera(options?: VideoStreamOptions): Promise<void>;
     startCaptions(options?: StartCaptionsAdapterOptions): Promise<void>;
     startNoiseSuppressionEffect(): Promise<void>;
     startScreenShare(): Promise<void>;
     startSpotlight(userIds?: string[]): Promise<void>;
-    // @beta
     startTogetherMode(): Promise<void>;
     startVideoBackgroundEffect(videoBackgroundEffect: VideoBackgroundEffect): Promise<void>;
     stopAllSpotlight(): Promise<void>;
@@ -1111,12 +1107,11 @@ export type CallErrors = {
 // @public
 export type CallErrorTarget = 'Call.addParticipant' | 'Call.dispose' | 'Call.feature' | 'Call.hangUp' | 'Call.hold' | 'Call.mute' | 'Call.muteIncomingAudio' | 'Call.off' | 'Call.on' | 'Call.removeParticipant' | 'Call.resume' | 'Call.sendDtmf' | 'Call.startAudio' | 'Call.startScreenSharing' | 'Call.startVideo' | 'Call.stopScreenSharing' | 'Call.stopAudio' | 'Call.stopVideo' | 'Call.unmute' | 'Call.unmuteIncomingAudio' | 'CallAgent.dispose' | 'CallAgent.feature' | 'CallAgent.join' | 'CallAgent.off' | 'CallAgent.on' | 'CallAgent.startCall' | 'CallClient.createCallAgent' | 'CallClient.createTeamsCallAgent' | 'CallClient.feature' | 'CallClient.getDeviceManager' | 'CallClient.getEnvironmentInfo' | 'DeviceManager.askDevicePermission' | 'DeviceManager.getCameras' | 'DeviceManager.getMicrophones' | 'DeviceManager.getSpeakers' | 'DeviceManager.off' | 'DeviceManager.on' | 'DeviceManager.selectMicrophone' | 'DeviceManager.selectSpeaker' | 'IncomingCall.accept' | 'IncomingCall.reject' | 'TeamsCall.addParticipant' | 'VideoEffectsFeature.startEffects' | /* @conditional-compile-remove(calling-beta-sdk) */ 'CallAgent.handlePushNotification' | /* @conditional-compile-remove(calling-beta-sdk) */ 'Call.admit' | /* @conditional-compile-remove(calling-beta-sdk) */ 'Call.rejectParticipant' | /* @conditional-compile-remove(calling-beta-sdk) */ 'Call.admitAll' | 'Call.mutedByOthers' | 'Call.muteAllRemoteParticipants' | 'Call.setConstraints';
 
-// @beta
+// @public
 export type CallFeatureStreamName = 'togetherMode';
 
-// @beta
+// @public
 export interface CallFeatureStreamState extends RemoteVideoStreamState {
-    // (undocumented)
     feature?: CallFeatureStreamName;
 }
 
@@ -1255,7 +1250,6 @@ export interface CallState {
     spotlight?: SpotlightCallFeatureState;
     startTime: Date;
     state: CallState_2;
-    // @beta
     togetherMode: TogetherModeCallFeatureState;
     totalParticipantCount?: number;
     transcription: TranscriptionCallFeature;
@@ -1282,7 +1276,6 @@ export interface CallWithChatAdapterManagement {
     allowUnsupportedBrowserVersion(): void;
     askDevicePermission(constrain: PermissionConstraints): Promise<DeviceAccess>;
     createStreamView(remoteUserId?: string, options?: VideoStreamOptions): Promise<void | CreateVideoStreamViewResult>;
-    // @beta
     createTogetherModeStreamView(options?: TogetherModeStreamOptions): Promise<void | TogetherModeStreamViewResult>;
     // @beta
     deleteImage(imageId: string): Promise<void>;
@@ -1291,7 +1284,6 @@ export interface CallWithChatAdapterManagement {
     disposeRemoteVideoStreamView(remoteUserId: string): Promise<void>;
     disposeScreenShareStreamView(remoteUserId: string): Promise<void>;
     disposeStreamView(remoteUserId?: string, options?: VideoStreamOptions): Promise<void>;
-    // @beta
     disposeTogetherModeStreamView(): Promise<void>;
     // (undocumented)
     downloadResourceToCache(resourceDetails: ResourceDetails): Promise<void>;
@@ -1335,7 +1327,6 @@ export interface CallWithChatAdapterManagement {
     setMicrophone(sourceInfo: AudioDeviceInfo): Promise<void>;
     setSpeaker(sourceInfo: AudioDeviceInfo): Promise<void>;
     setSpokenLanguage(language: string): Promise<void>;
-    // @beta
     setTogetherModeSceneSize(width: number, height: number): void;
     startCall(participants: string[], options?: StartCallOptions): Call | undefined;
     startCall(participants: (MicrosoftTeamsAppIdentifier | PhoneNumberIdentifier | CommunicationUserIdentifier | MicrosoftTeamsUserIdentifier | UnknownIdentifier)[], options?: StartCallOptions): Call | undefined;
@@ -1344,7 +1335,6 @@ export interface CallWithChatAdapterManagement {
     startNoiseSuppressionEffect(): Promise<void>;
     startScreenShare(): Promise<void>;
     startSpotlight(userIds?: string[]): Promise<void>;
-    // @beta
     startTogetherMode(): Promise<void>;
     startVideoBackgroundEffect(videoBackgroundEffect: VideoBackgroundEffect): Promise<void>;
     stopAllSpotlight(): Promise<void>;
@@ -2394,7 +2384,6 @@ export interface CommonCallingHandlers {
     onCreateLocalStreamView: (options?: VideoStreamOptions) => Promise<void | CreateVideoStreamViewResult>;
     // (undocumented)
     onCreateRemoteStreamView: (userId: string, options?: VideoStreamOptions) => Promise<void | CreateVideoStreamViewResult>;
-    // @beta
     onCreateTogetherModeStreamView: (options?: TogetherModeStreamOptions) => Promise<void | TogetherModeStreamViewResult>;
     // (undocumented)
     onDisposeLocalScreenShareStreamView: () => Promise<void>;
@@ -2406,7 +2395,6 @@ export interface CommonCallingHandlers {
     onDisposeRemoteStreamView: (userId: string) => Promise<void>;
     // (undocumented)
     onDisposeRemoteVideoStreamView: (userId: string) => Promise<void>;
-    // @beta
     onDisposeTogetherModeStreamView: () => Promise<void>;
     onForbidAudio?: (userIds: string[]) => Promise<void>;
     onForbidOthersAudio?: () => Promise<void>;
@@ -2452,7 +2440,6 @@ export interface CommonCallingHandlers {
     onSetCaptionLanguage: (language: string) => Promise<void>;
     // (undocumented)
     onSetSpokenLanguage: (language: string) => Promise<void>;
-    // @beta
     onSetTogetherModeSceneSize: (width: number, height: number) => void;
     // (undocumented)
     onStartCall: (participants: CommunicationIdentifier[], options?: StartCallOptions) => void;
@@ -2466,7 +2453,6 @@ export interface CommonCallingHandlers {
     onStartScreenShare: () => Promise<void>;
     // (undocumented)
     onStartSpotlight: (userIds?: string[]) => Promise<void>;
-    // @beta
     onStartTogetherMode: () => Promise<void>;
     // (undocumented)
     onStopAllSpotlight: () => Promise<void>;
@@ -4250,9 +4236,7 @@ export interface NotificationStackStrings {
     stopScreenShareGeneric?: NotificationStrings;
     stopVideoGeneric?: NotificationStrings;
     teamsMeetingCallNetworkQualityLow?: NotificationStrings;
-    // (undocumented)
     togetherModeEnded?: NotificationStrings;
-    // (undocumented)
     togetherModeStarted?: NotificationStrings;
     transcriptionStarted?: NotificationStrings;
     transcriptionStopped?: NotificationStrings;
@@ -5340,44 +5324,36 @@ export type TeamsOutboundCallAdapterArgs = TeamsCallAdapterArgsCommon & {
 // @public
 export const toFlatCommunicationIdentifier: (identifier: CommunicationIdentifier) => string;
 
-// @beta
+// @public
 export interface TogetherModeCallFeatureState {
-    // (undocumented)
     isActive: boolean;
     seatingPositions: TogetherModeParticipantSeatingState;
     streams: TogetherModeStreamsState;
 }
 
-// @beta
+// @public
 export type TogetherModeParticipantSeatingState = Record<string, TogetherModeSeatingPositionState>;
 
-// @beta
+// @public
 export interface TogetherModeSeatingPositionState {
-    // (undocumented)
     height: number;
-    // (undocumented)
     left: number;
-    // (undocumented)
     top: number;
-    // (undocumented)
     width: number;
 }
 
-// @beta
+// @public
 export interface TogetherModeStreamOptions extends VideoStreamOptions {
-    // (undocumented)
     viewKind?: 'main' | 'panoramic';
 }
 
-// @beta
+// @public
 export interface TogetherModeStreamsState {
-    // (undocumented)
     mainVideoStream?: CallFeatureStreamState;
 }
 
-// @beta
+// @public
 export interface TogetherModeStreamViewResult {
-    // (undocumented)
     mainVideoView?: CreateVideoStreamViewResult;
 }
 
@@ -5754,24 +5730,19 @@ export interface VideoGalleryStyles extends BaseCustomStyles {
     verticalGallery?: VerticalGalleryStyles;
 }
 
-// @beta
+// @public
 export type VideoGalleryTogetherModeParticipantPosition = Record<string, VideoGalleryTogetherModeSeatingInfo>;
 
-// @beta
+// @public
 export interface VideoGalleryTogetherModeSeatingInfo {
-    // (undocumented)
     height: number;
-    // (undocumented)
     left: number;
-    // (undocumented)
     top: number;
-    // (undocumented)
     width: number;
 }
 
-// @beta
+// @public
 export interface VideoGalleryTogetherModeStreams {
-    // (undocumented)
     mainVideoStream?: VideoGalleryStream;
 }
 
diff --git a/packages/communication-react/review/stable/communication-react.api.md b/packages/communication-react/review/stable/communication-react.api.md
index aee6cbc3aea..115a41fee64 100644
--- a/packages/communication-react/review/stable/communication-react.api.md
+++ b/packages/communication-react/review/stable/communication-react.api.md
@@ -297,11 +297,13 @@ export interface CallAdapterCallOperations {
     // (undocumented)
     addParticipant(participant: CommunicationUserIdentifier): Promise<void>;
     createStreamView(remoteUserId?: string, options?: VideoStreamOptions): Promise<void | CreateVideoStreamViewResult>;
+    createTogetherModeStreamView(options?: TogetherModeStreamOptions): Promise<void | TogetherModeStreamViewResult>;
     disposeLocalVideoStreamView(): Promise<void>;
     disposeRemoteVideoStreamView(remoteUserId: string): Promise<void>;
     disposeScreenShareStreamView(remoteUserId: string): Promise<void>;
     // @deprecated
     disposeStreamView(remoteUserId?: string, options?: VideoStreamOptions): Promise<void>;
+    disposeTogetherModeStreamView(): Promise<void>;
     forbidAudio(userIds: string[]): Promise<void>;
     forbidOthersAudio(): Promise<void>;
     forbidOthersVideo(): Promise<void>;
@@ -325,11 +327,13 @@ export interface CallAdapterCallOperations {
     sendDtmfTone(dtmfTone: DtmfTone_2): Promise<void>;
     setCaptionLanguage(language: string): Promise<void>;
     setSpokenLanguage(language: string): Promise<void>;
+    setTogetherModeSceneSize(width: number, height: number): void;
     startCamera(options?: VideoStreamOptions): Promise<void>;
     startCaptions(options?: StartCaptionsAdapterOptions): Promise<void>;
     startNoiseSuppressionEffect(): Promise<void>;
     startScreenShare(): Promise<void>;
     startSpotlight(userIds?: string[]): Promise<void>;
+    startTogetherMode(): Promise<void>;
     startVideoBackgroundEffect(videoBackgroundEffect: VideoBackgroundEffect): Promise<void>;
     stopAllSpotlight(): Promise<void>;
     stopCamera(): Promise<void>;
@@ -586,6 +590,7 @@ export type CallCompositeIcons = {
     JoinByPhoneWaitToBeAdmittedIcon?: JSX.Element;
     PeoplePaneMoreButton?: JSX.Element;
     StopAllSpotlightMenuButton?: JSX.Element;
+    TogetherModeLayout?: JSX.Element;
 };
 
 // @public
@@ -925,6 +930,14 @@ export type CallErrors = {
 // @public
 export type CallErrorTarget = 'Call.addParticipant' | 'Call.dispose' | 'Call.feature' | 'Call.hangUp' | 'Call.hold' | 'Call.mute' | 'Call.muteIncomingAudio' | 'Call.off' | 'Call.on' | 'Call.removeParticipant' | 'Call.resume' | 'Call.sendDtmf' | 'Call.startAudio' | 'Call.startScreenSharing' | 'Call.startVideo' | 'Call.stopScreenSharing' | 'Call.stopAudio' | 'Call.stopVideo' | 'Call.unmute' | 'Call.unmuteIncomingAudio' | 'CallAgent.dispose' | 'CallAgent.feature' | 'CallAgent.join' | 'CallAgent.off' | 'CallAgent.on' | 'CallAgent.startCall' | 'CallClient.createCallAgent' | 'CallClient.createTeamsCallAgent' | 'CallClient.feature' | 'CallClient.getDeviceManager' | 'CallClient.getEnvironmentInfo' | 'DeviceManager.askDevicePermission' | 'DeviceManager.getCameras' | 'DeviceManager.getMicrophones' | 'DeviceManager.getSpeakers' | 'DeviceManager.off' | 'DeviceManager.on' | 'DeviceManager.selectMicrophone' | 'DeviceManager.selectSpeaker' | 'IncomingCall.accept' | 'IncomingCall.reject' | 'TeamsCall.addParticipant' | 'VideoEffectsFeature.startEffects' | 'Call.mutedByOthers' | 'Call.muteAllRemoteParticipants' | 'Call.setConstraints';
 
+// @public
+export type CallFeatureStreamName = 'togetherMode';
+
+// @public
+export interface CallFeatureStreamState extends RemoteVideoStreamState {
+    feature?: CallFeatureStreamName;
+}
+
 // @public
 export type CallIdChangedListener = (event: {
     callId: string;
@@ -1053,6 +1066,7 @@ export interface CallState {
     spotlight?: SpotlightCallFeatureState;
     startTime: Date;
     state: CallState_2;
+    togetherMode: TogetherModeCallFeatureState;
     transcription: TranscriptionCallFeature;
     transfer: TransferFeature;
 }
@@ -1076,11 +1090,13 @@ export interface CallWithChatAdapterManagement {
     addParticipant(participant: CommunicationUserIdentifier): Promise<void>;
     askDevicePermission(constrain: PermissionConstraints): Promise<DeviceAccess>;
     createStreamView(remoteUserId?: string, options?: VideoStreamOptions): Promise<void | CreateVideoStreamViewResult>;
+    createTogetherModeStreamView(options?: TogetherModeStreamOptions): Promise<void | TogetherModeStreamViewResult>;
     deleteMessage(messageId: string): Promise<void>;
     disposeLocalVideoStreamView(): Promise<void>;
     disposeRemoteVideoStreamView(remoteUserId: string): Promise<void>;
     disposeScreenShareStreamView(remoteUserId: string): Promise<void>;
     disposeStreamView(remoteUserId?: string, options?: VideoStreamOptions): Promise<void>;
+    disposeTogetherModeStreamView(): Promise<void>;
     // (undocumented)
     downloadResourceToCache(resourceDetails: ResourceDetails): Promise<void>;
     fetchInitialData(): Promise<void>;
@@ -1122,6 +1138,7 @@ export interface CallWithChatAdapterManagement {
     setMicrophone(sourceInfo: AudioDeviceInfo): Promise<void>;
     setSpeaker(sourceInfo: AudioDeviceInfo): Promise<void>;
     setSpokenLanguage(language: string): Promise<void>;
+    setTogetherModeSceneSize(width: number, height: number): void;
     startCall(participants: string[], options?: StartCallOptions): Call | undefined;
     startCall(participants: (MicrosoftTeamsAppIdentifier | PhoneNumberIdentifier | CommunicationUserIdentifier | MicrosoftTeamsUserIdentifier | UnknownIdentifier)[], options?: StartCallOptions): Call | undefined;
     startCamera(options?: VideoStreamOptions): Promise<void>;
@@ -1129,6 +1146,7 @@ export interface CallWithChatAdapterManagement {
     startNoiseSuppressionEffect(): Promise<void>;
     startScreenShare(): Promise<void>;
     startSpotlight(userIds?: string[]): Promise<void>;
+    startTogetherMode(): Promise<void>;
     startVideoBackgroundEffect(videoBackgroundEffect: VideoBackgroundEffect): Promise<void>;
     stopAllSpotlight(): Promise<void>;
     stopCamera(): Promise<void>;
@@ -2087,6 +2105,7 @@ export interface CommonCallingHandlers {
     onCreateLocalStreamView: (options?: VideoStreamOptions) => Promise<void | CreateVideoStreamViewResult>;
     // (undocumented)
     onCreateRemoteStreamView: (userId: string, options?: VideoStreamOptions) => Promise<void | CreateVideoStreamViewResult>;
+    onCreateTogetherModeStreamView: (options?: TogetherModeStreamOptions) => Promise<void | TogetherModeStreamViewResult>;
     // (undocumented)
     onDisposeLocalScreenShareStreamView: () => Promise<void>;
     // (undocumented)
@@ -2097,6 +2116,7 @@ export interface CommonCallingHandlers {
     onDisposeRemoteStreamView: (userId: string) => Promise<void>;
     // (undocumented)
     onDisposeRemoteVideoStreamView: (userId: string) => Promise<void>;
+    onDisposeTogetherModeStreamView: () => Promise<void>;
     onForbidAudio?: (userIds: string[]) => Promise<void>;
     onForbidOthersAudio?: () => Promise<void>;
     onForbidOthersVideo?: () => Promise<void>;
@@ -2139,6 +2159,7 @@ export interface CommonCallingHandlers {
     onSetCaptionLanguage: (language: string) => Promise<void>;
     // (undocumented)
     onSetSpokenLanguage: (language: string) => Promise<void>;
+    onSetTogetherModeSceneSize: (width: number, height: number) => void;
     // (undocumented)
     onStartCall: (participants: CommunicationIdentifier[], options?: StartCallOptions) => void;
     // (undocumented)
@@ -2151,6 +2172,7 @@ export interface CommonCallingHandlers {
     onStartScreenShare: () => Promise<void>;
     // (undocumented)
     onStartSpotlight: (userIds?: string[]) => Promise<void>;
+    onStartTogetherMode: () => Promise<void>;
     // (undocumented)
     onStopAllSpotlight: () => Promise<void>;
     // (undocumented)
@@ -2690,6 +2712,7 @@ export const DEFAULT_COMPONENT_ICONS: {
     IncomingCallNotificationRejectIcon: React_2.JSX.Element;
     IncomingCallNotificationAcceptIcon: React_2.JSX.Element;
     IncomingCallNotificationAcceptWithVideoIcon: React_2.JSX.Element;
+    NotificationBarTogetherModeIcon: React_2.JSX.Element;
 };
 
 // @public
@@ -2786,6 +2809,7 @@ export const DEFAULT_COMPOSITE_ICONS: {
     JoinByPhoneWaitToBeAdmittedIcon?: JSX.Element | undefined;
     PeoplePaneMoreButton?: JSX.Element | undefined;
     StopAllSpotlightMenuButton?: JSX.Element | undefined;
+    TogetherModeLayout?: JSX.Element | undefined;
     ChevronLeft?: JSX.Element | undefined;
     ControlBarChatButtonActive?: JSX.Element | undefined;
     ControlBarChatButtonInactive?: JSX.Element | undefined;
@@ -2849,6 +2873,7 @@ export const DEFAULT_COMPOSITE_ICONS: {
     IncomingCallNotificationRejectIcon: React_2.JSX.Element;
     IncomingCallNotificationAcceptIcon: React_2.JSX.Element;
     IncomingCallNotificationAcceptWithVideoIcon: React_2.JSX.Element;
+    NotificationBarTogetherModeIcon: React_2.JSX.Element;
 };
 
 // @public
@@ -3754,6 +3779,8 @@ export interface NotificationStackStrings {
     stopScreenShareGeneric?: NotificationStrings;
     stopVideoGeneric?: NotificationStrings;
     teamsMeetingCallNetworkQualityLow?: NotificationStrings;
+    togetherModeEnded?: NotificationStrings;
+    togetherModeStarted?: NotificationStrings;
     transcriptionStarted?: NotificationStrings;
     transcriptionStopped?: NotificationStrings;
     transcriptionStoppedStillRecording?: NotificationStrings;
@@ -3783,7 +3810,7 @@ export interface NotificationStyles {
 }
 
 // @public (undocumented)
-export type NotificationTarget = 'assignedBreakoutRoomOpened' | 'assignedBreakoutRoomOpenedPromptJoin' | 'assignedBreakoutRoomChanged' | 'assignedBreakoutRoomClosed' | 'breakoutRoomJoined' | 'breakoutRoomClosingSoon' | 'capabilityTurnVideoOnPresent' | 'capabilityTurnVideoOnAbsent' | 'capabilityUnmuteMicPresent' | 'capabilityUnmuteMicAbsent';
+export type NotificationTarget = 'assignedBreakoutRoomOpened' | 'assignedBreakoutRoomOpenedPromptJoin' | 'assignedBreakoutRoomChanged' | 'assignedBreakoutRoomClosed' | 'breakoutRoomJoined' | 'breakoutRoomClosingSoon' | 'capabilityTurnVideoOnPresent' | 'capabilityTurnVideoOnAbsent' | 'capabilityUnmuteMicPresent' | 'capabilityUnmuteMicAbsent' | 'togetherModeStarted' | 'togetherModeEnded';
 
 // @public
 export type NotificationType = keyof NotificationStackStrings;
@@ -4416,8 +4443,8 @@ export interface StartCaptionsButtonStrings {
 export interface StatefulCallClient extends CallClient {
     createCallAgent(...args: Parameters<CallClient['createCallAgent']>): Promise<DeclarativeCallAgent>;
     createTeamsCallAgent(...args: Parameters<CallClient['createTeamsCallAgent']>): Promise<DeclarativeTeamsCallAgent>;
-    createView(callId: string | undefined, participantId: CommunicationIdentifier | undefined, stream: LocalVideoStreamState | RemoteVideoStreamState, options?: CreateViewOptions): Promise<CreateViewResult | undefined>;
-    disposeView(callId: string | undefined, participantId: CommunicationIdentifier | undefined, stream: LocalVideoStreamState | RemoteVideoStreamState): void;
+    createView(callId: string | undefined, participantId: CommunicationIdentifier | undefined, stream: LocalVideoStreamState | RemoteVideoStreamState | CallFeatureStreamState, options?: CreateViewOptions): Promise<CreateViewResult | undefined>;
+    disposeView(callId: string | undefined, participantId: CommunicationIdentifier | undefined, stream: LocalVideoStreamState | RemoteVideoStreamState | CallFeatureStreamState): void;
     getState(): CallClientState;
     offStateChange(handler: (state: CallClientState) => void): void;
     onStateChange(handler: (state: CallClientState) => void): void;
@@ -4603,6 +4630,39 @@ export interface TeamsIncomingCallState {
 // @public
 export const toFlatCommunicationIdentifier: (identifier: CommunicationIdentifier) => string;
 
+// @public
+export interface TogetherModeCallFeatureState {
+    isActive: boolean;
+    seatingPositions: TogetherModeParticipantSeatingState;
+    streams: TogetherModeStreamsState;
+}
+
+// @public
+export type TogetherModeParticipantSeatingState = Record<string, TogetherModeSeatingPositionState>;
+
+// @public
+export interface TogetherModeSeatingPositionState {
+    height: number;
+    left: number;
+    top: number;
+    width: number;
+}
+
+// @public
+export interface TogetherModeStreamOptions extends VideoStreamOptions {
+    viewKind?: 'main' | 'panoramic';
+}
+
+// @public
+export interface TogetherModeStreamsState {
+    mainVideoStream?: CallFeatureStreamState;
+}
+
+// @public
+export interface TogetherModeStreamViewResult {
+    mainVideoView?: CreateVideoStreamViewResult;
+}
+
 // @public
 export type TopicChangedListener = (event: {
     topic: string;
@@ -4765,7 +4825,7 @@ export interface VideoBackgroundReplacementEffect extends BackgroundReplacementC
 export const VideoGallery: (props: VideoGalleryProps) => JSX.Element;
 
 // @public (undocumented)
-export type VideoGalleryLayout = 'default' | 'floatingLocalVideo' | 'speaker' | 'focusedContent';
+export type VideoGalleryLayout = 'default' | 'floatingLocalVideo' | 'speaker' | 'togetherMode' | 'focusedContent';
 
 // @public
 export interface VideoGalleryLocalParticipant extends VideoGalleryParticipant {
@@ -4790,6 +4850,7 @@ export type VideoGalleryParticipant = {
 // @public
 export interface VideoGalleryProps {
     dominantSpeakers?: string[];
+    isTogetherModeActive?: boolean;
     layout?: VideoGalleryLayout;
     localParticipant: VideoGalleryLocalParticipant;
     localScreenShareView?: LocalScreenShareView;
@@ -4800,12 +4861,14 @@ export interface VideoGalleryProps {
     maxRemoteVideoStreams?: number;
     onCreateLocalStreamView?: (options?: VideoStreamOptions) => Promise<void | CreateVideoStreamViewResult>;
     onCreateRemoteStreamView?: (userId: string, options?: VideoStreamOptions) => Promise<void | CreateVideoStreamViewResult>;
+    onCreateTogetherModeStreamView?: (options?: TogetherModeStreamOptions) => Promise<void | TogetherModeStreamViewResult>;
     onDisposeLocalScreenShareStreamView?: () => Promise<void>;
     onDisposeLocalStreamView?: () => void;
     onDisposeRemoteScreenShareStreamView?: (userId: string) => Promise<void>;
     // @deprecated (undocumented)
     onDisposeRemoteStreamView?: (userId: string) => Promise<void>;
     onDisposeRemoteVideoStreamView?: (userId: string) => Promise<void>;
+    onDisposeTogetherModeStreamView?: () => Promise<void>;
     onForbidAudio?: (userIds: string[]) => Promise<void>;
     onForbidVideo?: (userIds: string[]) => Promise<void>;
     onMuteParticipant?: (userId: string) => Promise<void>;
@@ -4815,8 +4878,10 @@ export interface VideoGalleryProps {
     onRenderAvatar?: OnRenderAvatarCallback;
     onRenderLocalVideoTile?: (localParticipant: VideoGalleryLocalParticipant) => JSX.Element;
     onRenderRemoteVideoTile?: (remoteParticipant: VideoGalleryRemoteParticipant) => JSX.Element;
+    onSetTogetherModeSceneSize?: (width: number, height: number) => void;
     onStartLocalSpotlight?: () => Promise<void>;
     onStartRemoteSpotlight?: (userIds: string[]) => Promise<void>;
+    onStartTogetherMode?: () => Promise<void>;
     onStopLocalSpotlight?: () => Promise<void>;
     onStopRemoteSpotlight?: (userIds: string[]) => Promise<void>;
     onUnpinParticipant?: (userId: string) => void;
@@ -4829,8 +4894,11 @@ export interface VideoGalleryProps {
     showCameraSwitcherInLocalPreview?: boolean;
     showMuteIndicator?: boolean;
     spotlightedParticipants?: string[];
+    startTogetherModeEnabled?: boolean;
     strings?: Partial<VideoGalleryStrings>;
     styles?: VideoGalleryStyles;
+    togetherModeSeatingCoordinates?: VideoGalleryTogetherModeParticipantPosition;
+    togetherModeStreams?: VideoGalleryTogetherModeStreams;
     videoTilesOptions?: VideoTilesOptions;
 }
 
@@ -4853,6 +4921,10 @@ export type VideoGallerySelector = (state: CallClientState, props: CallingBaseSe
     optimalVideoCount?: number;
     spotlightedParticipants?: string[];
     maxParticipantsToSpotlight?: number;
+    isTogetherModeActive?: boolean;
+    startTogetherModeEnabled?: boolean;
+    togetherModeStreams?: VideoGalleryTogetherModeStreams;
+    togetherModeSeatingCoordinates?: VideoGalleryTogetherModeParticipantPosition;
 };
 
 // @public
@@ -4906,6 +4978,22 @@ export interface VideoGalleryStyles extends BaseCustomStyles {
     verticalGallery?: VerticalGalleryStyles;
 }
 
+// @public
+export type VideoGalleryTogetherModeParticipantPosition = Record<string, VideoGalleryTogetherModeSeatingInfo>;
+
+// @public
+export interface VideoGalleryTogetherModeSeatingInfo {
+    height: number;
+    left: number;
+    top: number;
+    width: number;
+}
+
+// @public
+export interface VideoGalleryTogetherModeStreams {
+    mainVideoStream?: VideoGalleryStream;
+}
+
 // @public
 export interface VideoStreamOptions {
     isMirrored?: boolean;
diff --git a/packages/react-components/src/components/NotificationStack.tsx b/packages/react-components/src/components/NotificationStack.tsx
index 9494b1b9f51..567296a4e8b 100644
--- a/packages/react-components/src/components/NotificationStack.tsx
+++ b/packages/react-components/src/components/NotificationStack.tsx
@@ -291,9 +291,15 @@ export interface NotificationStackStrings {
   capabilityUnmuteMicAbsent?: NotificationStrings;
 
   /* @conditional-compile-remove(together-mode) */
+  /**
+   * Message shown in notification when together mode is started
+   */
   togetherModeStarted?: NotificationStrings;
 
   /* @conditional-compile-remove(together-mode) */
+  /**
+   * Message shown in notification when together mode ends
+   */
   togetherModeEnded?: NotificationStrings;
 }
 
diff --git a/packages/react-components/src/types/TogetherModeTypes.ts b/packages/react-components/src/types/TogetherModeTypes.ts
index c12869708ec..a109f2e35d7 100644
--- a/packages/react-components/src/types/TogetherModeTypes.ts
+++ b/packages/react-components/src/types/TogetherModeTypes.ts
@@ -7,48 +7,65 @@ import { CreateVideoStreamViewResult, VideoGalleryStream, VideoStreamOptions } f
 /* @conditional-compile-remove(together-mode) */
 /**
  * Interface representing the result of a Together Mode stream view.
- * @beta
+ * @public
  */
 export interface TogetherModeStreamOptions extends VideoStreamOptions {
+  /**
+   * The kind of together mode view to be created. Default is 'main'.
+   */
   viewKind?: 'main' | 'panoramic';
 }
 /* @conditional-compile-remove(together-mode) */
 /**
  * Interface representing the result of a Together Mode stream view.
- * @beta
+ * @public
  */
 export interface TogetherModeStreamViewResult {
+  /**
+   * Together mode stream view id.
+   */
   mainVideoView?: CreateVideoStreamViewResult;
 }
 
 /* @conditional-compile-remove(together-mode) */
 /**
  * Interface representing the streams in Together Mode.
- * @beta
+ * @public
  */
 export interface VideoGalleryTogetherModeStreams {
+  /**
+   * The main video stream in Together Mode.
+   */
   mainVideoStream?: VideoGalleryStream;
 }
 
 /* @conditional-compile-remove(together-mode) */
 /**
  * Interface representing the seating information in Together Mode.
- * @beta
+ * @public
  */
 export interface VideoGalleryTogetherModeSeatingInfo {
-  /* The top left offset from the top of the together mode view.*/
+  /**
+   * The top left offset from the top of the together mode view.
+   */
   top: number;
-  /* The left offset position from the left of the together mode view. */
+  /**
+   * The left offset position from the left of the together mode view.
+   */
   left: number;
-  /*  The width of the seating area */
+  /**
+   *The width of the seating area
+   */
   width: number;
-  /* The height of the seating area. */
+  /**
+   * The height of the seating area.
+   */
   height: number;
 }
 
 /* @conditional-compile-remove(together-mode) */
 /**
  * Interface representing the position of a participant in Together Mode.
- * @beta
+ * @public
  */
 export type VideoGalleryTogetherModeParticipantPosition = Record<string, VideoGalleryTogetherModeSeatingInfo>;
diff --git a/packages/react-composites/src/composites/CallComposite/adapter/CallAdapter.ts b/packages/react-composites/src/composites/CallComposite/adapter/CallAdapter.ts
index 4cc07e6c512..c122c076373 100644
--- a/packages/react-composites/src/composites/CallComposite/adapter/CallAdapter.ts
+++ b/packages/react-composites/src/composites/CallComposite/adapter/CallAdapter.ts
@@ -627,17 +627,16 @@ export interface CallAdapterCallOperations {
    * @remarks
    * This method is implemented for composite
    *
-   * @param featureName - Name of feature to render
    * @param options - Options to control how video streams are rendered {@link @azure/communication-calling#VideoStreamOptions }
    *
-   * @beta
+   * @public
    */
   createTogetherModeStreamView(options?: TogetherModeStreamOptions): Promise<void | TogetherModeStreamViewResult>;
   /* @conditional-compile-remove(together-mode) */
   /**
    * Start Together mode.
    *
-   * @beta
+   * @public
    */
   startTogetherMode(): Promise<void>;
   /* @conditional-compile-remove(together-mode) */
@@ -650,7 +649,7 @@ export interface CallAdapterCallOperations {
    * @param width - Width of the container
    * @param height - Height of the container
    *
-   * @beta
+   * @public
    */
   setTogetherModeSceneSize(width: number, height: number): void;
 
@@ -662,10 +661,7 @@ export interface CallAdapterCallOperations {
    * This method is implemented for composite
    *
    *
-   * @param featureName - Name of the feature to dispose
-   * @param options - Options to control how video streams are rendered {@link @azure/communication-calling#VideoStreamOptions }
-   *
-   * @beta
+   * @public
    */
   disposeTogetherModeStreamView(): Promise<void>;
   /**
diff --git a/packages/react-composites/src/composites/CallWithChatComposite/adapter/CallWithChatAdapter.ts b/packages/react-composites/src/composites/CallWithChatComposite/adapter/CallWithChatAdapter.ts
index 3b4c541724a..7f332fb104b 100644
--- a/packages/react-composites/src/composites/CallWithChatComposite/adapter/CallWithChatAdapter.ts
+++ b/packages/react-composites/src/composites/CallWithChatComposite/adapter/CallWithChatAdapter.ts
@@ -238,7 +238,7 @@ export interface CallWithChatAdapterManagement {
    *
    * @param options - Options to control how video streams are rendered {@link @azure/communication-calling#VideoStreamOptions }
    *
-   * @beta
+   * @public
    */
   createTogetherModeStreamView(options?: TogetherModeStreamOptions): Promise<void | TogetherModeStreamViewResult>;
   /* @conditional-compile-remove(together-mode) */
@@ -249,7 +249,7 @@ export interface CallWithChatAdapterManagement {
    * This method is implemented for composite
    *
    *
-   * @beta
+   * @public
    */
   startTogetherMode(): Promise<void>;
   /* @conditional-compile-remove(together-mode) */
@@ -262,7 +262,7 @@ export interface CallWithChatAdapterManagement {
    * @param width - Width of the container
    * @param height - Height of the container
    *
-   * @beta
+   * @public
    */
   setTogetherModeSceneSize(width: number, height: number): void;
 
@@ -273,7 +273,7 @@ export interface CallWithChatAdapterManagement {
    * @remarks
    * This method is implemented for composite
    *
-   * @beta
+   * @public
    */
   disposeTogetherModeStreamView(): Promise<void>;
   /**
diff --git a/packages/react-composites/tests/browser/call/hermetic/fixture.ts b/packages/react-composites/tests/browser/call/hermetic/fixture.ts
index 73cf32eb6e7..3ed512d6968 100644
--- a/packages/react-composites/tests/browser/call/hermetic/fixture.ts
+++ b/packages/react-composites/tests/browser/call/hermetic/fixture.ts
@@ -431,7 +431,7 @@ const consumerCapabilitiesInRoomsCall = (): ParticipantCapabilities => ({
     isPresent: false,
     reason: 'CapabilityNotApplicableForTheCallType'
   },
-  /* @conditional-compile-remove(calling-beta-sdk) */
+  /* @conditional-compile-remove(together-mode) */
   startTogetherMode: { isPresent: false, reason: 'CapabilityNotApplicableForTheCallType' },
   /* @conditional-compile-remove(breakout-rooms) */
   joinBreakoutRooms: { isPresent: false, reason: 'CapabilityNotApplicableForTheCallType' },
@@ -481,7 +481,7 @@ const attendeeCapabilitiesInRoomsCall = (): ParticipantCapabilities => ({
     isPresent: false,
     reason: 'CapabilityNotApplicableForTheCallType'
   },
-  /* @conditional-compile-remove(calling-beta-sdk) */
+  /* @conditional-compile-remove(together-mode) */
   startTogetherMode: { isPresent: false, reason: 'CapabilityNotApplicableForTheCallType' },
   /* @conditional-compile-remove(breakout-rooms) */
   joinBreakoutRooms: { isPresent: false, reason: 'CapabilityNotApplicableForTheCallType' },
@@ -531,7 +531,7 @@ const presenterCapabilitiesInRoomsCall = (): ParticipantCapabilities => ({
     isPresent: true,
     reason: 'Capable'
   },
-  /* @conditional-compile-remove(calling-beta-sdk) */
+  /* @conditional-compile-remove(together-mode) */
   startTogetherMode: { isPresent: false, reason: 'CapabilityNotApplicableForTheCallType' },
   /* @conditional-compile-remove(breakout-rooms) */
   joinBreakoutRooms: { isPresent: false, reason: 'CapabilityNotApplicableForTheCallType' },
@@ -581,7 +581,7 @@ const presenterCapabilitiesInTeamsCall = (): ParticipantCapabilities => ({
     isPresent: true,
     reason: 'Capable'
   },
-  /* @conditional-compile-remove(calling-beta-sdk) */
+  /* @conditional-compile-remove(together-mode) */
   startTogetherMode: { isPresent: true, reason: 'Capable' },
   /* @conditional-compile-remove(breakout-rooms) */
   joinBreakoutRooms: { isPresent: true, reason: 'Capable' },
diff --git a/packages/react-composites/tests/browser/snapshots/stable/tests/browser/call/hermetic/TogetherModeOverlay.test.ts-snapshots/together-mode-all-participants-Desktop-Chrome-linux.png b/packages/react-composites/tests/browser/snapshots/stable/tests/browser/call/hermetic/TogetherModeOverlay.test.ts-snapshots/together-mode-all-participants-Desktop-Chrome-linux.png
new file mode 100644
index 00000000000..56b7335bf4d
Binary files /dev/null and b/packages/react-composites/tests/browser/snapshots/stable/tests/browser/call/hermetic/TogetherModeOverlay.test.ts-snapshots/together-mode-all-participants-Desktop-Chrome-linux.png differ
diff --git a/packages/react-composites/tests/browser/snapshots/stable/tests/browser/call/hermetic/TogetherModeOverlay.test.ts-snapshots/together-mode-all-participants-in-smaller-size-Desktop-Chrome-linux.png b/packages/react-composites/tests/browser/snapshots/stable/tests/browser/call/hermetic/TogetherModeOverlay.test.ts-snapshots/together-mode-all-participants-in-smaller-size-Desktop-Chrome-linux.png
new file mode 100644
index 00000000000..d2fb5f64b8d
Binary files /dev/null and b/packages/react-composites/tests/browser/snapshots/stable/tests/browser/call/hermetic/TogetherModeOverlay.test.ts-snapshots/together-mode-all-participants-in-smaller-size-Desktop-Chrome-linux.png differ
diff --git a/packages/react-composites/tests/browser/snapshots/stable/tests/browser/call/hermetic/TogetherModeOverlay.test.ts-snapshots/together-mode-participant-1-click-Desktop-Chrome-linux.png b/packages/react-composites/tests/browser/snapshots/stable/tests/browser/call/hermetic/TogetherModeOverlay.test.ts-snapshots/together-mode-participant-1-click-Desktop-Chrome-linux.png
new file mode 100644
index 00000000000..025d24efde4
Binary files /dev/null and b/packages/react-composites/tests/browser/snapshots/stable/tests/browser/call/hermetic/TogetherModeOverlay.test.ts-snapshots/together-mode-participant-1-click-Desktop-Chrome-linux.png differ
diff --git a/packages/react-composites/tests/browser/snapshots/stable/tests/browser/call/hermetic/TogetherModeOverlay.test.ts-snapshots/together-mode-view-icons-only-Desktop-Chrome-linux.png b/packages/react-composites/tests/browser/snapshots/stable/tests/browser/call/hermetic/TogetherModeOverlay.test.ts-snapshots/together-mode-view-icons-only-Desktop-Chrome-linux.png
new file mode 100644
index 00000000000..e03bf915610
Binary files /dev/null and b/packages/react-composites/tests/browser/snapshots/stable/tests/browser/call/hermetic/TogetherModeOverlay.test.ts-snapshots/together-mode-view-icons-only-Desktop-Chrome-linux.png differ
diff --git a/packages/react-composites/tests/browser/snapshots/stable/tests/browser/call/hermetic/TogetherModeOverlay.test.ts-snapshots/together-mode-view-mute-icon-Desktop-Chrome-linux.png b/packages/react-composites/tests/browser/snapshots/stable/tests/browser/call/hermetic/TogetherModeOverlay.test.ts-snapshots/together-mode-view-mute-icon-Desktop-Chrome-linux.png
new file mode 100644
index 00000000000..ff5d3e2a839
Binary files /dev/null and b/packages/react-composites/tests/browser/snapshots/stable/tests/browser/call/hermetic/TogetherModeOverlay.test.ts-snapshots/together-mode-view-mute-icon-Desktop-Chrome-linux.png differ
diff --git a/packages/react-composites/tests/browser/snapshots/stable/tests/browser/call/hermetic/TogetherModeOverlay.test.ts-snapshots/together-mode-view-option-all-participants-Desktop-Chrome-linux.png b/packages/react-composites/tests/browser/snapshots/stable/tests/browser/call/hermetic/TogetherModeOverlay.test.ts-snapshots/together-mode-view-option-all-participants-Desktop-Chrome-linux.png
new file mode 100644
index 00000000000..411d54bf3b9
Binary files /dev/null and b/packages/react-composites/tests/browser/snapshots/stable/tests/browser/call/hermetic/TogetherModeOverlay.test.ts-snapshots/together-mode-view-option-all-participants-Desktop-Chrome-linux.png differ
diff --git a/packages/react-composites/tests/browser/snapshots/stable/tests/browser/call/hermetic/TogetherModeOverlay.test.ts-snapshots/together-mode-view-option-all-participants-in-smaller-size-Desktop-Chrome-linux.png b/packages/react-composites/tests/browser/snapshots/stable/tests/browser/call/hermetic/TogetherModeOverlay.test.ts-snapshots/together-mode-view-option-all-participants-in-smaller-size-Desktop-Chrome-linux.png
new file mode 100644
index 00000000000..5ac1d896c1d
Binary files /dev/null and b/packages/react-composites/tests/browser/snapshots/stable/tests/browser/call/hermetic/TogetherModeOverlay.test.ts-snapshots/together-mode-view-option-all-participants-in-smaller-size-Desktop-Chrome-linux.png differ
diff --git a/packages/react-composites/tests/browser/snapshots/stable/tests/browser/call/hermetic/TogetherModeOverlay.test.ts-snapshots/together-mode-view-option-hidden-in-acs-call-Desktop-Chrome-linux.png b/packages/react-composites/tests/browser/snapshots/stable/tests/browser/call/hermetic/TogetherModeOverlay.test.ts-snapshots/together-mode-view-option-hidden-in-acs-call-Desktop-Chrome-linux.png
new file mode 100644
index 00000000000..b623eb6ef54
Binary files /dev/null and b/packages/react-composites/tests/browser/snapshots/stable/tests/browser/call/hermetic/TogetherModeOverlay.test.ts-snapshots/together-mode-view-option-hidden-in-acs-call-Desktop-Chrome-linux.png differ
diff --git a/packages/react-composites/tests/browser/snapshots/stable/tests/browser/call/hermetic/TogetherModeOverlay.test.ts-snapshots/together-mode-view-option-in-teams-call-Desktop-Chrome-linux.png b/packages/react-composites/tests/browser/snapshots/stable/tests/browser/call/hermetic/TogetherModeOverlay.test.ts-snapshots/together-mode-view-option-in-teams-call-Desktop-Chrome-linux.png
new file mode 100644
index 00000000000..86021ea3c62
Binary files /dev/null and b/packages/react-composites/tests/browser/snapshots/stable/tests/browser/call/hermetic/TogetherModeOverlay.test.ts-snapshots/together-mode-view-option-in-teams-call-Desktop-Chrome-linux.png differ
diff --git a/packages/react-composites/tests/browser/snapshots/stable/tests/browser/call/hermetic/TogetherModeOverlay.test.ts-snapshots/together-mode-view-option-in-teams-meeting-Desktop-Chrome-linux.png b/packages/react-composites/tests/browser/snapshots/stable/tests/browser/call/hermetic/TogetherModeOverlay.test.ts-snapshots/together-mode-view-option-in-teams-meeting-Desktop-Chrome-linux.png
new file mode 100644
index 00000000000..86021ea3c62
Binary files /dev/null and b/packages/react-composites/tests/browser/snapshots/stable/tests/browser/call/hermetic/TogetherModeOverlay.test.ts-snapshots/together-mode-view-option-in-teams-meeting-Desktop-Chrome-linux.png differ
diff --git a/packages/react-composites/tests/browser/snapshots/stable/tests/browser/call/hermetic/TogetherModeOverlay.test.ts-snapshots/together-mode-view-raisehand-icon-Desktop-Chrome-linux.png b/packages/react-composites/tests/browser/snapshots/stable/tests/browser/call/hermetic/TogetherModeOverlay.test.ts-snapshots/together-mode-view-raisehand-icon-Desktop-Chrome-linux.png
new file mode 100644
index 00000000000..0460cb91afe
Binary files /dev/null and b/packages/react-composites/tests/browser/snapshots/stable/tests/browser/call/hermetic/TogetherModeOverlay.test.ts-snapshots/together-mode-view-raisehand-icon-Desktop-Chrome-linux.png differ
diff --git a/packages/react-composites/tests/browser/snapshots/stable/tests/browser/call/hermetic/TogetherModeOverlay.test.ts-snapshots/together-mode-view-spotlight-icon-Desktop-Chrome-linux.png b/packages/react-composites/tests/browser/snapshots/stable/tests/browser/call/hermetic/TogetherModeOverlay.test.ts-snapshots/together-mode-view-spotlight-icon-Desktop-Chrome-linux.png
new file mode 100644
index 00000000000..5315549dee3
Binary files /dev/null and b/packages/react-composites/tests/browser/snapshots/stable/tests/browser/call/hermetic/TogetherModeOverlay.test.ts-snapshots/together-mode-view-spotlight-icon-Desktop-Chrome-linux.png differ


Reviews:
user: login: dmceachernmsft
state: APPROVED
author_association: MEMBER
submitted_at: 2025-03-17T17:03:31Z
user: login: JamesBurnside
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-03-17T20:51:20Z
user: login: JamesBurnside
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-03-17T20:51:26Z
user: login: JamesBurnside
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-03-17T20:51:41Z
user: login: JamesBurnside
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-03-17T20:52:47Z
user: login: JamesBurnside
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-03-17T20:53:34Z
user: login: JamesBurnside
state: APPROVED
author_association: MEMBER
submitted_at: 2025-03-18T00:32:01Z

Review comments:
diff_hunk: @@ -925,6 +930,15 @@ export type CallErrors = {
 // @public
 export type CallErrorTarget = 'Call.addParticipant' | 'Call.dispose' | 'Call.feature' | 'Call.hangUp' | 'Call.hold' | 'Call.mute' | 'Call.muteIncomingAudio' | 'Call.off' | 'Call.on' | 'Call.removeParticipant' | 'Call.resume' | 'Call.sendDtmf' | 'Call.startAudio' | 'Call.startScreenSharing' | 'Call.startVideo' | 'Call.stopScreenSharing' | 'Call.stopAudio' | 'Call.stopVideo' | 'Call.unmute' | 'Call.unmuteIncomingAudio' | 'CallAgent.dispose' | 'CallAgent.feature' | 'CallAgent.join' | 'CallAgent.off' | 'CallAgent.on' | 'CallAgent.startCall' | 'CallClient.createCallAgent' | 'CallClient.createTeamsCallAgent' | 'CallClient.feature' | 'CallClient.getDeviceManager' | 'CallClient.getEnvironmentInfo' | 'DeviceManager.askDevicePermission' | 'DeviceManager.getCameras' | 'DeviceManager.getMicrophones' | 'DeviceManager.getSpeakers' | 'DeviceManager.off' | 'DeviceManager.on' | 'DeviceManager.selectMicrophone' | 'DeviceManager.selectSpeaker' | 'IncomingCall.accept' | 'IncomingCall.reject' | 'TeamsCall.addParticipant' | 'VideoEffectsFeature.startEffects' | 'Call.mutedByOthers' | 'Call.muteAllRemoteParticipants' | 'Call.setConstraints';
 
+// @public
+export type CallFeatureStreamName = 'togetherMode';
+
+// @public
+export interface CallFeatureStreamState extends RemoteVideoStreamState {
+    // (undocumented)
path: packages/communication-react/review/stable/communication-react.api.md
user: login: JamesBurnside
body: This should be documented
created_at: 2025-03-17T20:51:20Z
author_association: MEMBER
diff_hunk: @@ -1053,6 +1067,8 @@ export interface CallState {
     spotlight?: SpotlightCallFeatureState;
     startTime: Date;
     state: CallState_2;
+    // @beta
path: packages/communication-react/review/stable/communication-react.api.md
user: login: JamesBurnside
body: `@public`
created_at: 2025-03-17T20:51:26Z
author_association: MEMBER
diff_hunk: @@ -2087,6 +2107,8 @@ export interface CommonCallingHandlers {
     onCreateLocalStreamView: (options?: VideoStreamOptions) => Promise<void | CreateVideoStreamViewResult>;
     // (undocumented)
     onCreateRemoteStreamView: (userId: string, options?: VideoStreamOptions) => Promise<void | CreateVideoStreamViewResult>;
+    // @beta
path: packages/communication-react/review/stable/communication-react.api.md
user: login: JamesBurnside
body: `@public`
created_at: 2025-03-17T20:51:41Z
author_association: MEMBER
diff_hunk: @@ -2087,6 +2107,8 @@ export interface CommonCallingHandlers {
     onCreateLocalStreamView: (options?: VideoStreamOptions) => Promise<void | CreateVideoStreamViewResult>;
     // (undocumented)
     onCreateRemoteStreamView: (userId: string, options?: VideoStreamOptions) => Promise<void | CreateVideoStreamViewResult>;
+    // @beta
path: packages/communication-react/review/stable/communication-react.api.md
user: login: JamesBurnside
body: Won't comment on each one of these, but all `// @beta`'s need updated to result in `@public`
created_at: 2025-03-17T20:52:47Z
author_association: MEMBER
diff_hunk: @@ -3754,6 +3785,10 @@ export interface NotificationStackStrings {
     stopScreenShareGeneric?: NotificationStrings;
     stopVideoGeneric?: NotificationStrings;
     teamsMeetingCallNetworkQualityLow?: NotificationStrings;
+    // (undocumented)
path: packages/communication-react/review/stable/communication-react.api.md
user: login: JamesBurnside
body: won't comment on each one, but we aim to have no `// (undocumented)` public functions/properties
created_at: 2025-03-17T20:53:34Z
author_association: MEMBER

PR comments:
user: login: github-actions[bot]
created_at: 2025-03-14T18:00:53Z
body: Failed to pass the composite UI Test. If this PR is for UI change and the error is snapshot mismatch, please add "update_snapshots" label to the PR for updating the snapshot.
author_association: CONTRIBUTOR
user: login: github-actions[bot]
created_at: 2025-03-14T18:12:33Z
body: Failed to pass the UI Test. If this PR is for UI change and the error is snapshot mismatch, please add "update_snapshots" label to the PR for updating the snapshot.
author_association: CONTRIBUTOR
user: login: JamesBurnside
created_at: 2025-03-17T17:07:13Z
body: PR needs a couple things:

- Functions that are now GA need marked `@public`
- Stable api.md needs updated (`rush switch-flavor: stable && rush build -t @azure/communication-react`)
- Change files (`rush changelog` ideally the change file contains the release notes you want in the changelog for this feature)
author_association: MEMBER
user: login: github-actions[bot]
created_at: 2025-03-17T17:07:24Z
body: Failed to pass the composite UI Test. If this PR is for UI change and the error is snapshot mismatch, please add "update_snapshots" label to the PR for updating the snapshot.
author_association: CONTRIBUTOR
user: login: github-actions[bot]
created_at: 2025-03-17T17:18:56Z
body: Failed to pass the UI Test. If this PR is for UI change and the error is snapshot mismatch, please add "update_snapshots" label to the PR for updating the snapshot.
author_association: CONTRIBUTOR
user: login: github-actions[bot]
created_at: 2025-03-17T19:37:56Z
body: Failed to pass the composite UI Test. If this PR is for UI change and the error is snapshot mismatch, please add "update_snapshots" label to the PR for updating the snapshot.
author_association: CONTRIBUTOR
user: login: github-actions[bot]
created_at: 2025-03-17T19:38:38Z
body: Storybook 8 URL https://60c7ae6891f0e90039d7cd54-fhhbuuyzez.chromatic.com/
author_association: CONTRIBUTOR
user: login: github-actions[bot]
created_at: 2025-03-17T19:48:44Z
body: Failed to pass the UI Test. If this PR is for UI change and the error is snapshot mismatch, please add "update_snapshots" label to the PR for updating the snapshot.
author_association: CONTRIBUTOR
user: login: github-actions[bot]
created_at: 2025-03-17T21:46:06Z
body: Failed to pass the composite UI Test. If this PR is for UI change and the error is snapshot mismatch, please add "update_snapshots" label to the PR for updating the snapshot.
author_association: CONTRIBUTOR
user: login: github-actions[bot]
created_at: 2025-03-17T21:47:35Z
body: Storybook 8 URL https://60c7ae6891f0e90039d7cd54-subjkchwzs.chromatic.com/
author_association: CONTRIBUTOR
user: login: github-actions[bot]
created_at: 2025-03-17T22:53:34Z
body: Storybook 8 URL https://60c7ae6891f0e90039d7cd54-miapsilxtu.chromatic.com/
author_association: CONTRIBUTOR
user: login: github-actions[bot]
created_at: 2025-03-17T22:58:44Z
body: Failed to pass the composite UI Test. If this PR is for UI change and the error is snapshot mismatch, please add "update_snapshots" label to the PR for updating the snapshot.
author_association: CONTRIBUTOR
user: login: github-actions[bot]
created_at: 2025-03-17T23:10:51Z
body: Storybook 8 URL https://60c7ae6891f0e90039d7cd54-zptmdgpgeh.chromatic.com/
author_association: CONTRIBUTOR
user: login: github-actions[bot]
created_at: 2025-03-17T23:16:37Z
body: Failed to pass the UI Test. If this PR is for UI change and the error is snapshot mismatch, please add "update_snapshots" label to the PR for updating the snapshot.
author_association: CONTRIBUTOR
user: login: github-actions[bot]
created_at: 2025-03-17T23:33:42Z
body: Storybook 8 URL https://60c7ae6891f0e90039d7cd54-ffqahaznae.chromatic.com/
author_association: CONTRIBUTOR
user: login: github-actions[bot]
created_at: 2025-03-17T23:36:03Z
body: ## @azure/communication-react jest test coverage for ***stable***.

|   | Lines | Statements | Functions | Branches |
| --- | :-------: | :-------: | :-------: | :-------: |
| Base |28093 / 44718 <br /> 62.82%|28093 / 44718 <br /> 62.82%|788 / 1438 <br /> 54.79%|2330 / 3706 <br /> 62.87%|
| Current |29299 / 45990 <br /> 63.7%|29299 / 45990 <br /> 63.7%|808 / 1475 <br /> 54.77%|2404 / 3819 <br /> 62.94%|
| Diff |1206 / 1272 <br /> 0.88%|1206 / 1272 <br /> 0.88%|20 / 37 <br /> -0.02%|74 / 113 <br /> 0.07%|
author_association: CONTRIBUTOR
user: login: github-actions[bot]
created_at: 2025-03-17T23:36:18Z
body: ## @azure/communication-react jest test coverage for ***beta***.

|   | Lines | Statements | Functions | Branches |
| --- | :-------: | :-------: | :-------: | :-------: |
| Base |58451 / 94401 <br /> 61.91%|58451 / 94401 <br /> 61.91%|1180 / 2697 <br /> 43.75%|3522 / 5828 <br /> 60.43%|
| Current |58500 / 94428 <br /> 61.95%|58500 / 94428 <br /> 61.95%|1180 / 2697 <br /> 43.75%|3539 / 5840 <br /> 60.59%|
| Diff |49 / 27 <br /> 0.04%|49 / 27 <br /> 0.04%|0 / 0 <br /> 0%|17 / 12 <br /> 0.16%|
author_association: CONTRIBUTOR
user: login: github-actions[bot]
created_at: 2025-03-17T23:38:36Z
body: Failed to pass the UI Test. If this PR is for UI change and the error is snapshot mismatch, please add "update_snapshots" label to the PR for updating the snapshot.
author_association: CONTRIBUTOR
user: login: github-actions[bot]
created_at: 2025-03-18T00:02:05Z
body: ## CallWithChat bundle size is ***not changed***.
  - Current size: 12401048
  - Base size: 12401048
  - Diff size: 0
author_association: CONTRIBUTOR
user: login: github-actions[bot]
created_at: 2025-03-18T00:02:07Z
body: ## Calling bundle size is ***not changed***.
  - Current size: 12401036
  - Base size: 12401036
  - Diff size: 0
author_association: CONTRIBUTOR
user: login: github-actions[bot]
created_at: 2025-03-18T00:02:07Z
body: ## Chat bundle size is ***not changed***.
  - Current size: 1775124
  - Base size: 1775124
  - Diff size: 0
author_association: CONTRIBUTOR
user: login: github-actions[bot]
created_at: 2025-03-18T00:05:05Z
body: Storybook 8 URL https://60c7ae6891f0e90039d7cd54-lhwmgypzpb.chromatic.com/
author_association: CONTRIBUTOR