Skip to main content

Goal

By the end of this guide you will have voice and video calling working in your React app — including the CometChatCallButtons component, incoming call notifications, and outgoing call screens.

Prerequisites

  • A working CometChat React UI Kit v7 setup (completed the Integration Guide)
  • CometChatUIKit.init() and login() completed before rendering
  • A CometChat plan that includes calling features enabled in your dashboard

Step 1: Install the Calls SDK

The calling feature requires the optional @cometchat/calls-sdk-javascript peer dependency:
npm install @cometchat/calls-sdk-javascript
This package provides the WebRTC layer for voice and video calls. It is loaded lazily by the UI Kit — no additional bundle cost until calling is actually used.

Step 2: Enable Calling in UIKitSettingsBuilder

Set .setCallingEnabled(true) on your UIKitSettingsBuilder during initialization:
src/main.tsx
import { CometChatUIKit, UIKitSettingsBuilder } from "@cometchat/chat-uikit-react";

const settings = new UIKitSettingsBuilder()
  .setAppId("YOUR_APP_ID")
  .setRegion("YOUR_REGION")
  .setAuthKey("YOUR_AUTH_KEY")
  .subscribePresenceForAllUsers()
  .setCallingEnabled(true)
  .build();

CometChatUIKit.init(settings).then(async () => {
  await CometChatUIKit.login("cometchat-uid-1");
  // Render your app
});
When calling is enabled, the UI Kit:
  • Registers the CallingPlugin for call-related message rendering
  • Lazy-loads call components (CometChatIncomingCall, CometChatOutgoingCall, CometChatOngoingCall) only when needed
  • Enables the CometChatCallButtons component to initiate calls
When calling is not enabled (the default), call components are not loaded and CometChatCallButtons renders nothing.

Step 3: Configure call settings

The Calls SDK uses the same appId and region from your UIKitSettings — no separate configuration is needed. The UI Kit passes these credentials to the Calls SDK automatically when calling is enabled.
The config prop on CometChatProvider accepts a CometChatGlobalConfig object for UI/behavior flags (hideReceipts, hideUserStatus, disableSoundForCalls, customSoundForCalls, callSettingsBuilder). It does not take a separate calling app ID or region.

Step 4: Add Call Buttons via CometChatMessageHeader

CometChatMessageHeader automatically renders voice and video call buttons when calling is enabled. No extra configuration needed — just render the header with a user or group:
import { CometChat } from "@cometchat/chat-sdk-javascript";
import {
  CometChatMessageHeader,
  CometChatMessageList,
  CometChatMessageComposer,
} from "@cometchat/chat-uikit-react";

function ChatPanel({ user }: { user: CometChat.User }) {
  return (
    <div style={{ display: "flex", flexDirection: "column", height: "100%" }}>
      <CometChatMessageHeader user={user} />
      <CometChatMessageList user={user} />
      <CometChatMessageComposer user={user} />
    </div>
  );
}
The header shows call buttons by default. To hide them, use hideVoiceCallButton or hideVideoCallButton:
<CometChatMessageHeader user={user} hideVoiceCallButton />
For group calls, pass the group prop instead:
<CometChatMessageHeader group={group} />
CometChatMessageHeader renders its call buttons automatically (via the CometChatMessageHeader.CallButtons sub-component) — you don’t import or render that sub-component separately. If you need call buttons outside the header, use the standalone CometChatCallButtons component.

Step 5: Verify with a voice call

With the setup complete, test a voice call:
  1. Open your app with two different users in separate browser tabs
  2. Click the voice call button (phone icon) in the chat header
  3. The caller sees the CometChatOutgoingCall screen with a “Calling…” indicator
  4. The receiver sees the CometChatIncomingCall overlay with accept/reject buttons
  5. Once accepted, both users enter the CometChatOngoingCall view with live audio
import { useState } from "react";
import { CometChat } from "@cometchat/chat-sdk-javascript";
import {
  CometChatProvider,
  CometChatConversations,
  CometChatMessageHeader,
  CometChatMessageList,
  CometChatMessageComposer,
} from "@cometchat/chat-uikit-react";

export default function App() {
  const [user, setUser] = useState<CometChat.User | null>(null);

  const handleConversationClick = (conversation: CometChat.Conversation) => {
    const conversationWith = conversation.getConversationWith();
    if (conversationWith instanceof CometChat.User) {
      setUser(conversationWith);
    }
  };

  return (
    <CometChatProvider>
      <div style={{ display: "flex", height: "100vh" }}>
        <div style={{ width: "360px", borderRight: "1px solid #eee" }}>
          <CometChatConversations onItemClick={handleConversationClick} />
        </div>
        <div style={{ flex: 1, display: "flex", flexDirection: "column" }}>
          {user && (
            <>
              <CometChatMessageHeader user={user} />
              <CometChatMessageList user={user} />
              <CometChatMessageComposer user={user} />
            </>
          )}
        </div>
      </div>
    </CometChatProvider>
  );
}

Step 6: Verify with a video call

Video calls work identically — click the video call button (camera icon) instead. The CometChatOngoingCall component renders a full video interface with:
  • Local and remote video streams
  • Mute/unmute audio toggle
  • Camera on/off toggle
  • End call button
No additional configuration is needed to switch between audio-only and video calls. The call type is determined by which button the user clicks.

Step 7: Render CometChatIncomingCall

CometChatIncomingCall must be rendered in your app — it is NOT auto-rendered by the UI Kit. Place it at the root level of your authenticated layout so it can display the incoming call overlay from anywhere:
import {
  CometChatProvider,
  CometChatIncomingCall,
  CometChatConversations,
  CometChatMessageHeader,
  CometChatMessageList,
  CometChatMessageComposer,
} from "@cometchat/chat-uikit-react";

export default function App() {
  const [user, setUser] = useState<CometChat.User | null>(null);

  const handleConversationClick = (conversation: CometChat.Conversation) => {
    const conversationWith = conversation.getConversationWith();
    if (conversationWith instanceof CometChat.User) {
      setUser(conversationWith);
    }
  };

  return (
    <CometChatProvider>
      <div style={{ display: "flex", height: "100vh" }}>
        <div style={{ width: "360px", borderRight: "1px solid #eee" }}>
          <CometChatConversations onItemClick={handleConversationClick} />
        </div>
        <div style={{ flex: 1, display: "flex", flexDirection: "column" }}>
          {user && (
            <>
              <CometChatMessageHeader user={user} />
              <CometChatMessageList user={user} />
              <CometChatMessageComposer user={user} />
            </>
          )}
        </div>
      </div>

      {/* Incoming call overlay — renders at root level, listens for call events */}
      <CometChatIncomingCall />
    </CometChatProvider>
  );
}
CometChatIncomingCall listens for incoming call events and displays an accept/reject overlay. When the user accepts, it transitions to the CometChatOngoingCall screen internally. You can customize its behavior with callbacks:
<CometChatIncomingCall
  onAccept={(call) => console.log("Call accepted:", call)}
  onDecline={(call) => console.log("Call declined:", call)}
/>
CometChatOutgoingCall is rendered automatically by the CometChatCallButtons component when the user initiates a call — you do not need to place it manually.

Summary

StepAction
1Install @cometchat/calls-sdk-javascript
2Set .setCallingEnabled(true) on UIKitSettingsBuilder
3(Optional) Configure call behavior via config prop on CometChatProvider
4Call buttons appear in CometChatMessageHeader automatically
5Test voice calls between two users
6Test video calls between two users
7(Optional) Customize incoming/outgoing call handlers

Next Steps