Documentation Index Fetch the complete documentation index at: https://www.cometchat.com/docs/llms.txt
Use this file to discover all available pages before exploring further.
AI Integration Quick Reference
Field Value Package @cometchat/chat-uikit-reactFramework React.js Components CometChatConversations, CometChatCallLogs, CometChatUsers, CometChatGroups, CometChatMessageHeader, CometChatMessageList, CometChatMessageComposerLayout Tabbed sidebar (Chats, Calls, Users, Groups) + message view Prerequisite Complete React.js Integration Steps 1–5 first Pattern Full-featured messaging app with multiple sections
This guide builds a tabbed messaging UI — Chats, Calls, Users, and Groups tabs in the sidebar, with a message view on the right. Good for full-featured apps that need more than just conversations.
This assumes you’ve already completed React.js Integration (project created, UI Kit installed, init + login working, CSS imported).
Fork the sandbox, insert your CometChat credentials (App ID, Region, Auth Key), and preview the UI in real time.
What You’re Building
Three sections working together:
Tab bar — switches between Chats, Calls, Users, and Groups
Sidebar — renders the list for the active tab (conversations, call logs, users, or groups)
Message view — header + messages + composer for the selected item
Step 1 — Create the Tab Component
Create a CometChatTabs folder inside src/:
Download the tab icons from the CometChat UI Kit assets folder on GitHub .
import { useState } from "react" ;
import chatsIcon from "./assets/chats.svg" ;
import callsIcon from "./assets/calls.svg" ;
import usersIcon from "./assets/users.svg" ;
import groupsIcon from "./assets/groups.svg" ;
import "./CometChatTabs.css" ;
export const CometChatTabs = ( props : {
onTabClicked ?: ( tabItem : { name : string ; icon ?: string }) => void ;
activeTab ?: string ;
}) => {
const { onTabClicked = () => {}, activeTab } = props ;
const [ hoverTab , setHoverTab ] = useState ( "" );
const tabItems = [
{ name: "CHATS" , icon: chatsIcon },
{ name: "CALLS" , icon: callsIcon },
{ name: "USERS" , icon: usersIcon },
{ name: "GROUPS" , icon: groupsIcon },
];
return (
< div className = "cometchat-tab-component" >
{ tabItems . map (( tabItem ) => (
< div
key = { tabItem . name }
className = "cometchat-tab-component__tab"
onClick = { () => onTabClicked ( tabItem ) }
>
< div
className = {
activeTab === tabItem . name . toLowerCase () ||
hoverTab === tabItem . name . toLowerCase ()
? "cometchat-tab-component__tab-icon cometchat-tab-component__tab-icon-active"
: "cometchat-tab-component__tab-icon"
}
style = {
tabItem . icon
? {
WebkitMaskImage: `url(" ${ tabItem . icon } ")` ,
maskImage: `url(" ${ tabItem . icon } ")` ,
}
: undefined
}
onMouseEnter = { () => setHoverTab ( tabItem . name . toLowerCase ()) }
onMouseLeave = { () => setHoverTab ( "" ) }
/>
< div
className = {
activeTab === tabItem . name . toLowerCase () ||
hoverTab === tabItem . name . toLowerCase ()
? "cometchat-tab-component__tab-text cometchat-tab-component__tab-text-active"
: "cometchat-tab-component__tab-text"
}
onMouseEnter = { () => setHoverTab ( tabItem . name . toLowerCase ()) }
onMouseLeave = { () => setHoverTab ( "" ) }
>
{ tabItem . name }
</ div >
</ div >
)) }
</ div >
);
};
.cometchat-tab-component {
display : flex ;
width : 100 % ;
padding : 0 px 8 px ;
align-items : flex-start ;
gap : 8 px ;
border-top : 1 px solid var ( --cometchat-border-color-light , #F5F5F5 );
border-right : 1 px solid var ( --cometchat-border-color-light , #F5F5F5 );
background : var ( --cometchat-background-color-01 , #FFF );
}
.cometchat-tab-component__tab {
display : flex ;
padding : 12 px 0 px 10 px 0 px ;
flex-direction : column ;
justify-content : center ;
align-items : center ;
gap : 4 px ;
flex : 1 0 0 ;
min-height : 48 px ;
}
.cometchat-tab-component__tab-icon {
display : flex ;
width : 32 px ;
height : 32 px ;
justify-content : center ;
align-items : center ;
background : var ( --cometchat-icon-color-secondary , #A1A1A1 );
-webkit-mask-size : contain ;
-webkit-mask-position : center ;
-webkit-mask-repeat : no-repeat ;
mask-size : contain ;
mask-position : center ;
mask-repeat : no-repeat ;
cursor : pointer ;
}
.cometchat-tab-component__tab-text {
color : var ( --cometchat-text-color-secondary , #727272 );
text-align : center ;
font : var ( --cometchat-font-caption1-medium , 500 12 px Roboto);
cursor : pointer ;
}
.cometchat-tab-component__tab-icon-active {
background : var ( --cometchat-icon-color-highlight );
}
.cometchat-tab-component__tab-text-active {
color : var ( --cometchat-text-color-highlight );
}
The sidebar renders the list for whichever tab is active, plus the tab bar at the bottom.
import { useEffect , useState } from "react" ;
import {
Call ,
Conversation ,
Group ,
User ,
CometChat ,
} from "@cometchat/chat-sdk-javascript" ;
import {
CometChatCallLogs ,
CometChatConversations ,
CometChatGroups ,
CometChatUIKitLoginListener ,
CometChatUsers ,
} from "@cometchat/chat-uikit-react" ;
import { CometChatTabs } from "../CometChatTabs/CometChatTabs" ;
import "./CometChatSelector.css" ;
interface SelectorProps {
onSelectorItemClicked ?: (
input : User | Group | Conversation | Call ,
type : string
) => void ;
}
export const CometChatSelector = ( props : SelectorProps ) => {
const { onSelectorItemClicked = () => {} } = props ;
const [ loggedInUser , setLoggedInUser ] = useState < CometChat . User | null >();
const [ activeItem , setActiveItem ] = useState <
CometChat . Conversation | CometChat . User | CometChat . Group | CometChat . Call | undefined
> ();
const [ activeTab , setActiveTab ] = useState < string >( "chats" );
useEffect (() => {
const user = CometChatUIKitLoginListener . getLoggedInUser ();
setLoggedInUser ( user );
}, []);
return (
<>
{ loggedInUser && (
<>
{ activeTab === "chats" ? (
< CometChatConversations
activeConversation = {
activeItem instanceof CometChat . Conversation ? activeItem : undefined
}
onItemClick = { ( e ) => {
setActiveItem ( e );
onSelectorItemClicked ( e , "updateSelectedItem" );
} }
/>
) : activeTab === "calls" ? (
< CometChatCallLogs
activeCall = {
activeItem instanceof CometChat . Call ? activeItem : undefined
}
onItemClick = { ( e : Call ) => {
setActiveItem ( e );
onSelectorItemClicked ( e , "updateSelectedItemCall" );
} }
/>
) : activeTab === "users" ? (
< CometChatUsers
activeUser = {
activeItem instanceof CometChat . User ? activeItem : undefined
}
onItemClick = { ( e ) => {
setActiveItem ( e );
onSelectorItemClicked ( e , "updateSelectedItemUser" );
} }
/>
) : activeTab === "groups" ? (
< CometChatGroups
activeGroup = {
activeItem instanceof CometChat . Group ? activeItem : undefined
}
onItemClick = { ( e ) => {
setActiveItem ( e );
onSelectorItemClicked ( e , "updateSelectedItemGroup" );
} }
/>
) : null }
</>
) }
< CometChatTabs
activeTab = { activeTab }
onTabClicked = { ( item ) => setActiveTab ( item . name . toLowerCase ()) }
/>
</>
);
};
/* Menu icon in conversation header */
.selector-wrapper .cometchat-conversations .cometchat-list__header-menu .cometchat-button__icon {
background : var ( --cometchat-icon-color-primary );
}
.cometchat-conversations .cometchat-list__header-menu .cometchat-button__icon:hover {
background : var ( --cometchat-icon-color-highlight );
}
.cometchat-list__header-search-bar {
border-right : none ;
}
.cometchat .cometchat-menu-list__sub-menu-list-item {
text-align : left ;
}
.cometchat .cometchat-conversations .cometchat-menu-list__sub-menu-list {
width : 212 px ;
top : 40 px !important ;
left : 172 px !important ;
}
/* Logged-in user section */
#logged-in-user {
border-bottom : 2 px solid var ( --cometchat-border-color-default , #E8E8E8 );
}
#logged-in-user .cometchat-menu-list__sub-menu-item-title ,
#logged-in-user .cometchat-menu-list__sub-menu-list-item {
cursor : default ;
}
.cometchat-menu-list__sub-menu-list-item-icon-log-out {
background-color : var ( --cometchat-error-color , #F44649 );
}
.cometchat-menu-list__sub-menu-item-title-log-out {
color : var ( --cometchat-error-color , #F44649 );
}
.chat-menu .cometchat .cometchat-menu-list__sub-menu-item-title {
cursor : pointer ;
}
.chat-menu .cometchat .cometchat-menu-list__sub-menu {
box-shadow : none ;
}
.chat-menu .cometchat .cometchat-menu-list__sub-menu-icon {
background-color : var ( --cometchat-icon-color-primary , #141414 );
width : 24 px ;
height : 24 px ;
}
Key points:
The activeTab state drives which list component renders — CometChatConversations, CometChatCallLogs, CometChatUsers, or CometChatGroups.
Each list component passes its selection back to the parent via onSelectorItemClicked with a type string so the parent knows what was selected.
CometChatTabs renders at the bottom of the sidebar.
Step 3 — Update App.tsx and App.css
Wire everything together. The app handles selections from any tab — conversations, users, groups, or calls.
import { useState } from "react" ;
import {
CometChatMessageComposer ,
CometChatMessageHeader ,
CometChatMessageList ,
} from "@cometchat/chat-uikit-react" ;
import { CometChat } from "@cometchat/chat-sdk-javascript" ;
import { CometChatSelector } from "./CometChatSelector/CometChatSelector" ;
import "./App.css" ;
import "@cometchat/chat-uikit-react/css-variables.css" ;
function App () {
const [ selectedUser , setSelectedUser ] = useState < CometChat . User | undefined >( undefined );
const [ selectedGroup , setSelectedGroup ] = useState < CometChat . Group | undefined >( undefined );
const [ selectedCall , setSelectedCall ] = useState < CometChat . Call | undefined >( undefined );
return (
< div className = "conversations-with-messages" >
{ /* Sidebar — tabs + list */ }
< div className = "conversations-wrapper" >
< CometChatSelector
onSelectorItemClicked = { ( activeItem ) => {
let item = activeItem ;
// Extract user/group from Conversation object
if ( activeItem instanceof CometChat . Conversation ) {
item = activeItem . getConversationWith ();
}
if ( item instanceof CometChat . User ) {
setSelectedUser ( item as CometChat . User );
setSelectedGroup ( undefined );
setSelectedCall ( undefined );
} else if ( item instanceof CometChat . Group ) {
setSelectedUser ( undefined );
setSelectedGroup ( item as CometChat . Group );
setSelectedCall ( undefined );
} else if ( item instanceof CometChat . Call ) {
// Add custom logic for call details here
setSelectedUser ( undefined );
setSelectedGroup ( undefined );
setSelectedCall ( item as CometChat . Call );
}
} }
/>
</ div >
{ /* Message view */ }
{ selectedUser || selectedGroup || selectedCall ? (
< div className = "messages-wrapper" >
< CometChatMessageHeader user = { selectedUser } group = { selectedGroup } />
< CometChatMessageList user = { selectedUser } group = { selectedGroup } />
< CometChatMessageComposer user = { selectedUser } group = { selectedGroup } />
</ div >
) : (
< div className = "empty-conversation" >
Select a conversation to start chatting
</ div >
) }
</ div >
);
}
export default App ;
@import url ( "@cometchat/chat-uikit-react/css-variables.css" );
#root {
text-align : center ;
width : 100 vw ;
height : 100 vh ;
background-color : #282c34 ;
}
/* Two-panel layout */
.conversations-with-messages {
display : flex ;
height : 100 % ;
width : 100 % ;
flex-direction : row ;
}
/* Left panel — tabs + list */
.conversations-wrapper {
height : 100 vh ;
width : 480 px ;
overflow : hidden ;
display : flex ;
flex-direction : column ;
}
.conversations-wrapper > .cometchat {
overflow : hidden ;
}
/* Right panel — messages */
.messages-wrapper {
width : 100 % ;
height : 100 vh ;
display : flex ;
flex-direction : column ;
}
/* Empty state */
.empty-conversation {
height : 100 vh ;
width : 100 % ;
display : flex ;
justify-content : center ;
align-items : center ;
background : var ( --cometchat-background-color-03 , #F5F5F5 );
color : var ( --cometchat-text-color-secondary , #727272 );
font : var ( --cometchat-font-body-regular , 400 14 px Roboto);
}
.cometchat .cometchat-message-composer {
border-radius : 0 px ;
}
How it works:
Selections from any tab (Chats, Calls, Users, Groups) flow through the same onSelectorItemClicked callback.
Conversation items are unwrapped via getConversationWith() to extract the underlying User or Group.
Call selections are tracked separately in selectedCall — add your own call details UI as needed.
Only one of selectedUser / selectedGroup / selectedCall is set at a time — the others are cleared.
Step 4 — Run the Project
You should see the tab bar at the bottom of the sidebar. Switch between Chats, Calls, Users, and Groups — tapping any item loads the message view on the right.
Next Steps
Theming Customize colors, fonts, and styles to match your brand
Components Overview Browse all prebuilt UI components
React.js Integration Back to the main setup guide
Core Features Chat features included out of the box