Skip to main content
The CometChat Calls SDK provides three layout modes for displaying participants during a call. You can set the initial layout in call settings or change it programmatically during the call.

Available Layouts

Tile Layout

The default grid layout that displays all participants equally sized in a grid pattern.
CometChatCalls.setLayout('TILE');
Displays one main participant with other participants in a sidebar. Useful when focusing on a presenter or active speaker.
CometChatCalls.setLayout('SIDEBAR');

Spotlight Layout

Focuses on a single participant with minimal UI for others. Ideal for presentations or when one participant needs full attention.
CometChatCalls.setLayout('SPOTLIGHT');

Set Initial Layout

Configure the initial layout when creating call settings:
import { CometChatCalls } from '@cometchat/calls-sdk-react-native';

const callSettings = new CometChatCalls.CallSettingsBuilder()
  .setMode(CometChatCalls.CALL_MODE.DEFAULT) // or SPOTLIGHT
  .build();
ModeDescription
CometChatCalls.CALL_MODE.DEFAULTStarts with Tile layout
CometChatCalls.CALL_MODE.SPOTLIGHTStarts with Spotlight layout

Change Layout During Call

Change the layout programmatically at any time during the call:
// Switch to Tile layout
CometChatCalls.setLayout('TILE');

// Switch to Sidebar layout
CometChatCalls.setLayout('SIDEBAR');

// Switch to Spotlight layout
CometChatCalls.setLayout('SPOTLIGHT');

Listen for Layout Changes

Subscribe to layout change events:
const unsubscribe = CometChatCalls.addEventListener('onCallLayoutChanged', (layout) => {
  console.log('Layout changed to:', layout);
  // Update UI state if needed
});

// Cleanup
unsubscribe();

Spotlight Mode Options

When using Spotlight layout, you can configure video tile interactions:
const callSettings = new CometChatCalls.CallSettingsBuilder()
  .setMode(CometChatCalls.CALL_MODE.SPOTLIGHT)
  .enableVideoTileClick(true)  // Allow clicking tiles to spotlight
  .enableVideoTileDrag(true)   // Allow dragging tiles
  .build();
OptionDefaultDescription
enableVideoTileClicktrueClick a participant tile to spotlight them
enableVideoTileDragtrueDrag tiles to reposition in Spotlight mode

Pin Participant

Pin a specific participant to the main view in Sidebar or Spotlight layouts:
// Pin a participant
const participantId = 'participant_pid';
CometChatCalls.pinParticipant(participantId, 'human');

// Pin a screen share
CometChatCalls.pinParticipant(participantId, 'screen-share');

// Unpin
CometChatCalls.unpinParticipant();

Automatic Layout Changes

The SDK automatically switches to Sidebar layout when:
  • A participant starts screen sharing
  • A participant is pinned
When screen sharing stops or the participant is unpinned, the layout returns to the previous state if it was programmatically set.

Complete Example

import React, { useState, useEffect } from 'react';
import { View, TouchableOpacity, Text, StyleSheet } from 'react-native';
import { CometChatCalls } from '@cometchat/calls-sdk-react-native';

type Layout = 'TILE' | 'SIDEBAR' | 'SPOTLIGHT';

function LayoutControls() {
  const [currentLayout, setCurrentLayout] = useState<Layout>('TILE');

  useEffect(() => {
    const unsubscribe = CometChatCalls.addEventListener(
      'onCallLayoutChanged',
      (layout: Layout) => {
        setCurrentLayout(layout);
      }
    );

    return () => unsubscribe();
  }, []);

  const layouts: Layout[] = ['TILE', 'SIDEBAR', 'SPOTLIGHT'];

  return (
    <View style={styles.container}>
      <Text style={styles.label}>Layout: {currentLayout}</Text>
      <View style={styles.buttons}>
        {layouts.map((layout) => (
          <TouchableOpacity
            key={layout}
            style={[
              styles.button,
              currentLayout === layout && styles.activeButton,
            ]}
            onPress={() => CometChatCalls.setLayout(layout)}
          >
            <Text
              style={[
                styles.buttonText,
                currentLayout === layout && styles.activeButtonText,
              ]}
            >
              {layout}
            </Text>
          </TouchableOpacity>
        ))}
      </View>
    </View>
  );
}

const styles = StyleSheet.create({
  container: {
    padding: 16,
  },
  label: {
    color: '#fff',
    fontSize: 14,
    marginBottom: 8,
  },
  buttons: {
    flexDirection: 'row',
    gap: 8,
  },
  button: {
    backgroundColor: '#333',
    paddingHorizontal: 16,
    paddingVertical: 8,
    borderRadius: 8,
  },
  activeButton: {
    backgroundColor: '#6851D6',
  },
  buttonText: {
    color: '#999',
    fontSize: 12,
    fontWeight: '600',
  },
  activeButtonText: {
    color: '#fff',
  },
});

export default LayoutControls;