Tip: You can fork the sandbox, insert your CometChat credentials (App ID, Region, Auth Key.) in the code, and immediately preview how the UI and messages respond in real time.
User Interface Preview

- Sidebar (Conversation List) – Displays recent conversations with active users and groups.
- Message View – Shows the selected chat with real-time messages.
- Message Input Box – Allows users to send messages seamlessly.
Step-by-Step Guide
Step 1: Create a Tab Component
To manage navigation, let’s build aCometChatTabs component. This component will render different tabs and allow switching between sections dynamically.
Folder Structure
Create aCometChatTabs folder inside your src directory and add the following files:
Report incorrect code
Copy
Ask AI
src/
│── CometChatTabs/
│ ├── assets # These are the images you need to save
│ │ ├── chats.svg
│ │ ├── calls.svg
│ │ ├── users.svg
│ │ ├── groups.svg
│ ├── CometChatTabs.tsx
│ ├── CometChatTabs.css
Download the Icons
These icons are available in the CometChat UI Kit assets folder. You can find them at:🔗 GitHub Assets Folder
Implementation
- TypeScript
- CSS
CometChatTabs.tsx
Report incorrect code
Copy
Ask AI
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>
)
}
CometChatTabs.css
Report incorrect code
Copy
Ask AI
.cometchat-tab-component {
display: flex;
width: 100%;
padding: 0px 8px;
align-items: flex-start;
gap: 8px;
border-top: 1px solid var(--cometchat-border-color-light, #F5F5F5);
border-right: 1px solid var(--cometchat-border-color-light, #F5F5F5);
background: var(--cometchat-background-color-01, #FFF);
}
.cometchat-tab-component__tab {
display: flex;
padding: 12px 0px 10px 0px;
flex-direction: column;
justify-content: center;
align-items: center;
gap: 4px;
flex: 1 0 0;
min-height: 48px;
}
.cometchat-tab-component__tab-icon {
display: flex;
width: 32px;
height: 32px;
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 12px 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);
}
Step 2: Create Sidebar
Let’s create theSidebar component which will render different conversations.
Folder Structure
Create aCometChatSelector folder inside your src directory and add the following files:
Report incorrect code
Copy
Ask AI
src/
│── CometChatSelector/
│ ├── CometChatSelector.tsx
│ ├── CometChatSelector.css
- TypeScript
- CSS
CometChatSelector.tsx
Report incorrect code
Copy
Ask AI
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;
onHide?: () => void;
onNewChatClicked?: () => 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 loggedInUsers = CometChatUIKitLoginListener.getLoggedInUser();
setLoggedInUser(loggedInUsers)
}, [])
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: { name: string; icon?: string; }) => {
setActiveTab(item.name.toLowerCase())
}} />
</>
);
}
CometChatSelector.css
Report incorrect code
Copy
Ask AI
.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: 212px;
top: 40px !important;
left: 172px !important;
}
#logged-in-user {
border-bottom: 2px 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: 24px;
height: 24px;
}
Step 3: Update App
Now we will update theApp.tsx & App.css files to import these new components as below,
- TypeScript
- CSS
App.tsx
Report incorrect code
Copy
Ask AI
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">
<div className="conversations-wrapper">
<CometChatSelector onSelectorItemClicked={(activeItem) => {
let item = activeItem;
if (activeItem instanceof CometChat.Conversation) {
item = activeItem.getConversationWith();
}
if (item instanceof CometChat.User) {
setSelectedUser(item as CometChat.User);
setSelectedCall(undefined);
setSelectedGroup(undefined);
} else if (item instanceof CometChat.Group) {
setSelectedUser(undefined);
setSelectedGroup(item as CometChat.Group);
setSelectedCall(undefined);
}
else if (item instanceof CometChat.Call) {
//custom logic to open call details
setSelectedUser(undefined);
setSelectedGroup(undefined);
setSelectedCall(item as CometChat.Call);
}
}} />
</div>
{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 Conversation to start</div>
)}
</div>
);
};
export default App;
App.css
Report incorrect code
Copy
Ask AI
#root {
text-align: center;
width: 100vw;
height: 100vh;
background-color: #282c34;
}
.conversations-with-messages {
display: flex;
height: 100%;
width: 100%;
flex-direction: row;
}
.conversations-wrapper {
height: 100vh;
width: 480px;
overflow: hidden;
display: flex;
flex-direction: column;
}
.conversations-wrapper>.cometchat {
overflow: hidden;
}
.messages-wrapper {
width: 100%;
height: 100vh;
display: flex;
flex-direction: column;
}
.empty-conversation {
height: 100vh;
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 14px Roboto);
}
.cometchat .cometchat-message-composer {
border-radius: 0px;
}
Step 4: Run the project
Report incorrect code
Copy
Ask AI
npm start
Next Steps
Enhance the User Experience
- Advanced Customizations – Personalize the chat UI to align with your brand.