Skip to main content
{
  "component": "CometChatUsers",
  "package": "@cometchat/chat-uikit-react",
  "import": "import { CometChatUsers } from \"@cometchat/chat-uikit-react\";",
  "cssImport": "import \"@cometchat/chat-uikit-react/css-variables.css\";",
  "description": "Searchable, scrollable list of all available users with avatar, name, and online/offline status.",
  "cssRootClass": ".cometchat-users",
  "primaryOutput": {
    "prop": "onItemClick",
    "type": "(user: CometChat.User) => void"
  },
  "props": {
    "data": {
      "usersRequestBuilder": {
        "type": "CometChat.UsersRequestBuilder",
        "default": "SDK default (30 per page)",
        "note": "Pass the builder, not the result of .build()"
      },
      "searchRequestBuilder": {
        "type": "CometChat.UsersRequestBuilder",
        "default": "undefined"
      },
      "activeUser": {
        "type": "CometChat.User",
        "default": "undefined"
      },
      "searchKeyword": {
        "type": "string",
        "default": "\"\""
      },
      "sectionHeaderKey": {
        "type": "keyof CometChat.User",
        "default": "getName"
      }
    },
    "callbacks": {
      "onItemClick": "(user: CometChat.User) => void",
      "onSelect": "(user: CometChat.User, selected: boolean) => void",
      "onError": "((error: CometChat.CometChatException) => void) | null",
      "onEmpty": "() => void"
    },
    "visibility": {
      "hideSearch": { "type": "boolean", "default": false },
      "hideError": { "type": "boolean", "default": false },
      "hideUserStatus": { "type": "boolean", "default": false },
      "showSectionHeader": { "type": "boolean", "default": true },
      "showScrollbar": { "type": "boolean", "default": false },
      "showSelectedUsersPreview": { "type": "boolean", "default": false }
    },
    "behavior": {
      "disableLoadingState": { "type": "boolean", "default": false }
    },
    "selection": {
      "selectionMode": {
        "type": "SelectionMode",
        "values": ["SelectionMode.single (0)", "SelectionMode.multiple (1)", "SelectionMode.none (2)"],
        "default": "SelectionMode.none"
      }
    },
    "viewSlots": {
      "itemView": "(user: CometChat.User) => JSX.Element",
      "leadingView": "(user: CometChat.User) => JSX.Element",
      "titleView": "(user: CometChat.User) => JSX.Element",
      "subtitleView": "(user: CometChat.User) => JSX.Element",
      "trailingView": "(user: CometChat.User) => JSX.Element",
      "headerView": "JSX.Element",
      "loadingView": "JSX.Element",
      "emptyView": "JSX.Element",
      "errorView": "JSX.Element",
      "options": "(user: CometChat.User) => CometChatOption[]"
    }
  },
  "events": [],
  "subscribedEvents": [
    {
      "name": "CometChatUserEvents.ccUserBlocked",
      "payload": "CometChat.User",
      "description": "Updates blocked user in list"
    },
    {
      "name": "CometChatUserEvents.ccUserUnblocked",
      "payload": "CometChat.User",
      "description": "Updates unblocked user in list"
    }
  ],
  "sdkListeners": [
    "onUserOnline",
    "onUserOffline"
  ],
  "compositionExample": {
    "description": "User list wired to message view",
    "components": [
      "CometChatUsers",
      "CometChatMessageHeader",
      "CometChatMessageList",
      "CometChatMessageComposer"
    ],
    "flow": "onItemClick emits CometChat.User -> pass to MessageHeader, MessageList, MessageComposer"
  },
  "types": {
    "CometChatOption": {
      "id": "string | undefined",
      "title": "string | undefined",
      "iconURL": "string | undefined",
      "onClick": "(() => void) | undefined"
    },
    "SelectionMode": {
      "single": 0,
      "multiple": 1,
      "none": 2
    }
  }
}

Where It Fits

CometChatUsers is a contact list component. It renders all available users and emits the selected CometChat.User via onItemClick. Wire it to CometChatMessageHeader, CometChatMessageList, and CometChatMessageComposer to build a standard two-panel chat layout.
import { useState } from "react";
import {
  CometChatUsers,
  CometChatMessageHeader,
  CometChatMessageList,
  CometChatMessageComposer,
} from "@cometchat/chat-uikit-react";
import { CometChat } from "@cometchat/chat-sdk-javascript";
import "@cometchat/chat-uikit-react/css-variables.css";

function ChatApp() {
  const [selectedUser, setSelectedUser] = useState<CometChat.User>();

  return (
    <div style={{ display: "flex", height: "100vh", width: "100vw" }}>
      <div style={{ width: 480, height: "100%" }}>
        <CometChatUsers onItemClick={(user) => setSelectedUser(user)} />
      </div>
      {selectedUser ? (
        <div style={{ flex: 1, display: "flex", flexDirection: "column" }}>
          <CometChatMessageHeader user={selectedUser} />
          <CometChatMessageList user={selectedUser} />
          <CometChatMessageComposer user={selectedUser} />
        </div>
      ) : (
        <div style={{ flex: 1, display: "grid", placeItems: "center", background: "#F5F5F5", color: "#727272" }}>
          Select a user
        </div>
      )}
    </div>
  );
}

Minimal Render

import { CometChatUsers } from "@cometchat/chat-uikit-react";
import "@cometchat/chat-uikit-react/css-variables.css";

function UsersDemo() {
  return (
    <div style={{ width: "100%", height: "100%" }}>
      <CometChatUsers />
    </div>
  );
}

export default UsersDemo;
Root CSS class: .cometchat-users

Filtering Users

Pass a CometChat.UsersRequestBuilder to usersRequestBuilder. Pass the builder instance — not the result of .build().
import { CometChatUsers } from "@cometchat/chat-uikit-react";
import { CometChat } from "@cometchat/chat-sdk-javascript";

function FilteredUsers() {
  return (
    <CometChatUsers
      usersRequestBuilder={
        new CometChat.UsersRequestBuilder().friendsOnly(true).setLimit(15)
      }
    />
  );
}

Filter Recipes

RecipeCode
Friends onlynew CometChat.UsersRequestBuilder().friendsOnly(true)
Online users onlynew CometChat.UsersRequestBuilder().setStatus("online")
Limit to 15 per pagenew CometChat.UsersRequestBuilder().setLimit(15)
Search by keywordnew CometChat.UsersRequestBuilder().setSearchKeyword("alice")
Hide blocked usersnew CometChat.UsersRequestBuilder().hideBlockedUsers(true)
Filter by rolesnew CometChat.UsersRequestBuilder().setRoles(["admin", "moderator"])
Filter by tagsnew CometChat.UsersRequestBuilder().setTags(["vip"])
Specific UIDsnew CometChat.UsersRequestBuilder().setUIDs(["uid1", "uid2"])
Default page size is 30. The component uses infinite scroll — the next page loads as the user scrolls to the bottom. A separate searchRequestBuilder can be passed to filter the search list independently from the main list. Refer to UsersRequestBuilder for the full builder API.

Actions and Events

Callback Props

onItemClick

Fires when a user row is tapped. Primary navigation hook — set the active user and render the message view.
import { CometChatUsers } from "@cometchat/chat-uikit-react";
import { CometChat } from "@cometchat/chat-sdk-javascript";

function UsersWithClick() {
  const handleItemClick = (user: CometChat.User) => {
    console.log("Selected:", user.getName());
  };

  return <CometChatUsers onItemClick={handleItemClick} />;
}

onSelect

Fires when a user is checked/unchecked in selection mode. Requires selectionMode to be set.
import { useState } from "react";
import {
  CometChatUsers,
  SelectionMode,
} from "@cometchat/chat-uikit-react";
import { CometChat } from "@cometchat/chat-sdk-javascript";

function BatchSelectDemo() {
  const [selected, setSelected] = useState<Set<string>>(new Set());

  const handleSelect = (user: CometChat.User, isSelected: boolean) => {
    setSelected((prev) => {
      const next = new Set(prev);
      const uid = user.getUid();
      isSelected ? next.add(uid) : next.delete(uid);
      return next;
    });
  };

  return (
    <CometChatUsers
      selectionMode={SelectionMode.multiple}
      onSelect={handleSelect}
    />
  );
}

onEmpty

Fires when the user list fetch returns zero results.
import { CometChatUsers } from "@cometchat/chat-uikit-react";

function UsersWithEmptyHandler() {
  return (
    <CometChatUsers onEmpty={() => console.log("No users available")} />
  );
}

onError

Fires on internal errors (network failure, auth issue, SDK exception).
import { CometChatUsers } from "@cometchat/chat-uikit-react";
import { CometChat } from "@cometchat/chat-sdk-javascript";

function UsersWithErrorHandler() {
  return (
    <CometChatUsers
      onError={(error: CometChat.CometChatException) => {
        console.error("CometChatUsers error:", error);
      }}
    />
  );
}

Global UI Events

The component subscribes to CometChatUserEvents internally:
EventInternal behavior
CometChatUserEvents.ccUserBlockedUpdates the blocked user in the list
CometChatUserEvents.ccUserUnblockedUpdates the unblocked user in the list
CometChatUsers does not emit any custom UI events.

SDK Events (Real-Time, Automatic)

The component listens to these SDK events internally. No manual attachment needed unless additional side effects are required.
SDK ListenerInternal behavior
onUserOnlineUpdates the user’s status dot to online
onUserOfflineUpdates the user’s status dot to offline
Automatic: user presence changes (online/offline), blocked/unblocked state.
In React 18 StrictMode, useEffect runs twice on mount in development. The component handles listener cleanup internally, but any additional listeners added alongside the component need cleanup in the useEffect return function to avoid duplicate event handling.

Custom View Slots

Each slot replaces a section of the default UI. Slots that accept a user parameter receive the CometChat.User object for that row.
SlotSignatureReplaces
itemView(user: CometChat.User) => JSX.ElementEntire list item row
leadingView(user: CometChat.User) => JSX.ElementAvatar / left section
titleView(user: CometChat.User) => JSX.ElementName / title text
subtitleView(user: CometChat.User) => JSX.ElementSubtitle text
trailingView(user: CometChat.User) => JSX.ElementRight section
headerViewJSX.ElementEntire header bar
loadingViewJSX.ElementLoading spinner
emptyViewJSX.ElementEmpty state
errorViewJSX.ElementError state
options(user: CometChat.User) => CometChatOption[]Context menu / hover actions

itemView

Replace the entire list item row. Default:
Customized:
import { CometChat } from "@cometchat/chat-sdk-javascript";
import { CometChatUsers, CometChatListItem } from "@cometchat/chat-uikit-react";

function UsersDemo() {
  const getItemView = (user: CometChat.User) => {
    const status = user.getStatus();

    return (
      <div
        className={`cometchat-users__list-item cometchat-users__list-item-${status}
          ${status === "online" ? `cometchat-users__list-item-active` : ""}
          `}
      >
        <CometChatListItem
          title={user.getName()}
          subtitleView={user.getStatus()}
          avatarURL={user.getAvatar()}
          avatarName={user.getName()}
        />
      </div>
    );
  };

  return <CometChatUsers itemView={getItemView} />;
}

leadingView

Replace the avatar / left section.
import { CometChat } from "@cometchat/chat-sdk-javascript";
import { CometChatUsers, CometChatAvatar } from "@cometchat/chat-uikit-react";

function LeadingViewUsers() {
  const getLeadingView = (user: CometChat.User) => {
    return (
      <div className="users__leading-view">
        <CometChatAvatar
          image={user.getAvatar()}
          name={user.getName()}
        />
      </div>
    );
  };

  return <CometChatUsers leadingView={getLeadingView} />;
}

trailingView

Replace the right section.
import { CometChat } from "@cometchat/chat-sdk-javascript";
import { CometChatUsers } from "@cometchat/chat-uikit-react";

function TrailingViewUsers() {
  const getTrailingView = (user: CometChat.User) => {
    const tag = user.getTags()?.[0] ?? "";
    return (
      <div className="users__trailing-view">
        <span className="users__trailing-view-text">{tag}</span>
      </div>
    );
  };

  return <CometChatUsers trailingView={getTrailingView} />;
}

titleView

Replace the name / title text. Role badge inline example.
import { CometChat } from "@cometchat/chat-sdk-javascript";
import { CometChatUsers } from "@cometchat/chat-uikit-react";

function TitleViewUsers() {
  const getTitleView = (user: CometChat.User) => {
    return (
      <div className="users__title-view">
        <span className="users__title-view-name">{user.getName()}</span>
        <span className="users__title-view-type">{user.getRole()}</span>
      </div>
    );
  };

  return <CometChatUsers titleView={getTitleView} />;
}

subtitleView

Replace the subtitle text for each user. Default:
Customized:
import { CometChat } from "@cometchat/chat-sdk-javascript";
import { CometChatUsers } from "@cometchat/chat-uikit-react";

function SubtitleViewUsers() {
  const getSubtitleView = (user: CometChat.User) => {
    return (
      <div className="users-subtitle">
        Last Active At: {new Date(user.getLastActiveAt() * 1000).toLocaleString()}
      </div>
    );
  };

  return <CometChatUsers subtitleView={getSubtitleView} />;
}

headerView

Replace the entire header bar.
import {
  CometChatUsers,
  CometChatButton,
  getLocalizedString,
} from "@cometchat/chat-uikit-react";

function CustomHeaderUsers() {
  return (
    <CometChatUsers
      headerView={
        <div className="users__header">
          <div className="users__header__title">
            {getLocalizedString("user_title")}
          </div>
          <CometChatButton onClick={() => { /* handle click */ }} />
        </div>
      }
    />
  );
}

options

Replace the context menu / hover actions on each user item. Default:
Customized:
import { CometChat } from "@cometchat/chat-sdk-javascript";
import {
  CometChatOption,
  CometChatUsers,
} from "@cometchat/chat-uikit-react";

function CustomOptionsUsers() {
  const getOptions = (user: CometChat.User) => [
    new CometChatOption({
      id: "delete",
      title: "Delete",
      onClick: () => { /* delete logic */ },
    }),
    new CometChatOption({
      id: "block",
      title: "Block",
      onClick: () => { /* block logic */ },
    }),
  ];

  return <CometChatUsers options={getOptions} />;
}
// CometChatOption interface
interface CometChatOption {
  id?: string;       // Unique identifier
  title?: string;    // Display text
  iconURL?: string;  // Icon asset URL
  onClick?: () => void; // Click handler
}

Common Patterns

Custom empty state with CTA

import { CometChatUsers } from "@cometchat/chat-uikit-react";

function EmptyStateUsers() {
  return (
    <CometChatUsers
      emptyView={
        <div style={{ textAlign: "center", padding: 40 }}>
          <p>No users found</p>
          <button onClick={() => { /* invite users */ }}>
            Invite users
          </button>
        </div>
      }
    />
  );
}
import { CometChatUsers } from "@cometchat/chat-uikit-react";
import { CometChat } from "@cometchat/chat-sdk-javascript";

function FriendsOnlyUsers() {
  return (
    <CometChatUsers
      usersRequestBuilder={
        new CometChat.UsersRequestBuilder().friendsOnly(true).setLimit(15)
      }
    />
  );
}

Multi-select with preview strip

import { CometChatUsers, SelectionMode } from "@cometchat/chat-uikit-react";
import { CometChat } from "@cometchat/chat-sdk-javascript";

function MultiSelectUsers() {
  return (
    <CometChatUsers
      selectionMode={SelectionMode.multiple}
      showSelectedUsersPreview={true}
      onSelect={(user: CometChat.User, selected: boolean) => {
        console.log(user.getName(), selected);
      }}
    />
  );
}

Hide all chrome — minimal list

import { CometChatUsers } from "@cometchat/chat-uikit-react";

function MinimalUsers() {
  return (
    <CometChatUsers
      hideSearch={true}
      hideUserStatus={true}
      showSectionHeader={false}
    />
  );
}

CSS Architecture

The component uses CSS custom properties (design tokens) defined in @cometchat/chat-uikit-react/css-variables.css. The cascade:
  1. Global tokens (e.g., --cometchat-primary-color, --cometchat-background-color-01) are set on the .cometchat root wrapper.
  2. Component CSS (.cometchat-users) consumes these tokens via var() with fallback values.
  3. Overrides target .cometchat-users descendant selectors in a global stylesheet.
To scope overrides to a single instance when multiple CometChatUsers exist on the same page, wrap the component in a container and scope selectors:
.sidebar-left .cometchat-users .cometchat-avatar {
  border-radius: 8px;
}
Overrides survive component updates because the component never sets inline styles on these elements — all styling flows through CSS classes and custom properties.

Key Selectors

TargetSelector
Root.cometchat-users
List item.cometchat-users__list-item
Active item.cometchat-users__list-item-active .cometchat-list-item
Online status.cometchat-users__list-item-online .cometchat-list-item__status
Avatar.cometchat-users__list-item .cometchat-avatar
Leading view.cometchat-users__list-item .cometchat-list-item__leading-view
Body.cometchat-users .cometchat-list-item__body
Empty state.cometchat-users__empty-state-view
Error state.cometchat-users__error-state-view
Shimmer loading.cometchat-users__shimmer
Shimmer item.cometchat-users__shimmer-item
Shimmer avatar.cometchat-users__shimmer-item-avatar
Shimmer title.cometchat-users__shimmer-item-title
Selected preview.cometchat-users__selected-preview
Selected chip.cometchat-users__selected-preview-chip
Chip name.cometchat-users__selected-preview-chip-name
Chip close button.cometchat-users__selected-preview-chip-close-button

Example: Brand-themed users

.cometchat .cometchat-users .cometchat-list__header-title {
  background-color: #fce9ea;
  color: #e5484d;
  font-family: "Times New Roman";
}

.cometchat .cometchat-users .cometchat-list-item__body-title {
  overflow: hidden;
  color: #141414;
  text-overflow: ellipsis;
  font-family: "Times New Roman";
}

.cometchat-list-item__leading-view {
  background: #f0999b;
  border-radius: 9.6px;
}

Customization Matrix

What to changeWhereProperty/APIExample
Override behavior on user interactionComponent propson<Event> callbacksonItemClick={(u) => setActive(u)}
Filter which users appearComponent propsusersRequestBuilderusersRequestBuilder={new CometChat.UsersRequestBuilder().friendsOnly(true)}
Toggle visibility of UI elementsComponent propshide<Feature> / show<Feature> boolean propshideSearch={true}
Replace a section of the list itemComponent props<slot>View render propsitemView={(user) => <div>...</div>}
Change colors, fonts, spacingGlobal CSSTarget .cometchat-users class.cometchat-users .cometchat-avatar { border-radius: 8px; }

Accessibility

The component renders a scrollable list of interactive items. Each user row is keyboard-focusable and activates on Enter/Space. The context menu (options) is accessible via keyboard. Avatar images include the user name as alt text. Section headers (A, B, C…) provide visual grouping for alphabetical navigation. For screen readers, the user list is rendered as a semantic list. Status indicators (online/offline) use CSS mask images — add aria-label attributes via itemView if screen reader descriptions are needed for these visual indicators.

Props

All props are optional unless noted.

activeUser

Highlights the specified user in the list.
TypeCometChat.User
Defaultundefined
Must be a reference-equal object from the SDK; a manually constructed object will not match.

disableLoadingState

Disables the loading state while fetching users.
Typeboolean
Defaultfalse
Useful when updating the request builder without clearing the list.

emptyView

Custom component displayed when there are no users.
TypeJSX.Element
DefaultBuilt-in empty state

errorView

Custom component displayed when an error occurs.
TypeJSX.Element
DefaultBuilt-in error state
Hidden when hideError={true}.

headerView

Custom component rendered as the entire header bar.
TypeJSX.Element
DefaultBuilt-in header with title and search

hideError

Hides the default and custom error views.
Typeboolean
Defaultfalse
Also suppresses errorView if set.

hideSearch

Hides the default search bar.
Typeboolean
Defaultfalse

hideUserStatus

Hides the online/offline status indicator.
Typeboolean
Defaultfalse

itemView

Custom renderer for the entire list item row.
Type(user: CometChat.User) => JSX.Element
DefaultBuilt-in list item

leadingView

Custom renderer for the avatar / left section.
Type(user: CometChat.User) => JSX.Element
DefaultBuilt-in avatar

loadingView

Custom component displayed during the loading state.
TypeJSX.Element
DefaultBuilt-in shimmer

onEmpty

Callback fired when the user list is empty.
Type() => void
Defaultundefined

onError

Callback fired when the component encounters an error.
Type((error: CometChat.CometChatException) => void) | null
Defaultundefined

onItemClick

Callback fired when a user row is clicked.
Type(user: CometChat.User) => void
Defaultundefined

onSelect

Callback fired when a user is selected/deselected. Requires selectionMode to be set.
Type(user: CometChat.User, selected: boolean) => void
Defaultundefined

options

Custom context menu / hover actions for each user item.
Type(user: CometChat.User) => CometChatOption[]
Defaultundefined
class CometChatOption {
  id?: string;
  title?: string;
  iconURL?: string;
  onClick?: () => void;
}

searchKeyword

Pre-fills the search and filters the user list.
Typestring
Default""

searchRequestBuilder

Request builder with search parameters to fetch users.
TypeCometChat.UsersRequestBuilder
Defaultundefined
If the search input is not empty, the search keyword of this request builder is set to the text in the search input.

sectionHeaderKey

The property on the user object used to extract the section header character.
Typekeyof CometChat.User
DefaultgetName
Only relevant when showSectionHeader={true}.

selectionMode

Enables single or multi-select checkboxes on list items.
TypeSelectionMode
DefaultSelectionMode.none
enum SelectionMode {
  single,    // 0
  multiple,  // 1
  none,      // 2
}
Must pair with onSelect to capture selections.

showScrollbar

Shows the scrollbar in the user list.
Typeboolean
Defaultfalse

showSectionHeader

Displays alphabetical section headers (A, B, C…).
Typeboolean
Defaulttrue

showSelectedUsersPreview

Shows a preview strip of selected users when selectionMode is multiple.
Typeboolean
Defaultfalse
Each chip displays avatar, name, and a close button to remove the user.

subtitleView

Custom renderer for the subtitle text.
Type(user: CometChat.User) => JSX.Element
Defaultundefined

titleView

Custom renderer for the name / title text.
Type(user: CometChat.User) => JSX.Element
DefaultBuilt-in title

trailingView

Custom renderer for the right section.
Type(user: CometChat.User) => JSX.Element
DefaultBuilt-in trailing view

usersRequestBuilder

Controls which users load and in what order.
TypeCometChat.UsersRequestBuilder
DefaultSDK default (30 per page)
Pass the builder instance, not the result of .build().

Events

CometChatUsers does not emit custom UI events. It subscribes to:
EventPayloadInternal behavior
CometChatUserEvents.ccUserBlockedCometChat.UserUpdates blocked user in list
CometChatUserEvents.ccUserUnblockedCometChat.UserUpdates unblocked user in list

CSS Selectors

TargetSelector
Root.cometchat-users
Hide scrollbar variant.cometchat-users-hide-scrollbar
List item.cometchat-users__list-item
Active item.cometchat-users__list-item-active .cometchat-list-item
Online status indicator.cometchat-users__list-item-online .cometchat-list-item__status
Avatar.cometchat-users__list-item .cometchat-avatar
Leading view.cometchat-users__list-item .cometchat-list-item__leading-view
Body.cometchat-users .cometchat-list-item__body
Empty state.cometchat-users__empty-state-view
Empty state icon.cometchat-users__empty-state-view-icon
Empty state title.cometchat-users__empty-state-view-body-title
Empty state description.cometchat-users__empty-state-view-body-description
Error state.cometchat-users__error-state-view
Error state icon.cometchat-users__error-state-view-icon
Error state title.cometchat-users__error-state-view-body-title
Error state description.cometchat-users__error-state-view-body-description
Shimmer loading.cometchat-users__shimmer
Shimmer item.cometchat-users__shimmer-item
Shimmer avatar.cometchat-users__shimmer-item-avatar
Shimmer title.cometchat-users__shimmer-item-title
Selected preview.cometchat-users__selected-preview
Selected preview container.cometchat-users__selected-preview-container
Selected chip.cometchat-users__selected-preview-chip
Chip avatar.cometchat-users__selected-preview-chip .cometchat-avatar
Chip name.cometchat-users__selected-preview-chip-name
Chip close button.cometchat-users__selected-preview-chip-close-button