Skip to main content

Documentation Index

Fetch the complete documentation index at: https://cometchat-22654f5b-react-uikit-v7.mintlify.app/llms.txt

Use this file to discover all available pages before exploring further.

{
  "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": "A scrollable, searchable list of users with real-time status updates, selection modes, and infinite scroll pagination.",
  "cssRootClass": ".cometchat-users",
  "primaryOutput": {
    "prop": "onItemClick",
    "type": "(user: CometChat.User) => void"
  },
  "subComponents": [
    "CometChatUsers.Root",
    "CometChatUsers.List",
    "CometChatUsers.Item",
    "CometChatUsers.Header",
    "CometChatUsers.SearchBar",
    "CometChatUsers.SectionHeader",
    "CometChatUsers.EmptyState",
    "CometChatUsers.ErrorState",
    "CometChatUsers.LoadingState",
    "CometChatUsers.SelectedPreview"
  ],
  "props": {
    "data": {
      "requestBuilder": { "type": "CometChat.UsersRequestBuilder", "default": "limit 30" },
      "searchRequestBuilder": { "type": "CometChat.UsersRequestBuilder", "default": "undefined" },
      "searchKeyword": { "type": "string", "default": "\"\"" },
      "activeUser": { "type": "CometChat.User", "default": "undefined" },
      "sectionHeaderKey": { "type": "keyof CometChat.User", "default": "\"getName\"" }
    },
    "callbacks": {
      "onItemClick": { "type": "(user: CometChat.User) => void", "default": "undefined" },
      "onSelect": { "type": "(user: CometChat.User, selected: boolean) => void", "default": "undefined" },
      "onError": { "type": "(error: unknown) => void", "default": "undefined" },
      "onEmpty": { "type": "() => void", "default": "undefined" }
    },
    "visibility": {
      "hideUserStatus": { "type": "boolean", "default": "false" },
      "showScrollbar": { "type": "boolean", "default": "false" }
    },
    "behavior": {
      "selectionMode": { "type": "'none' | 'single' | 'multiple'", "default": "'none'" },
      "options": { "type": "(user: CometChat.User) => CometChatUserOption[]", "default": "undefined" }
    },
    "viewSlots": {
      "leadingView": { "type": "(user: CometChat.User) => ReactNode", "default": "undefined" },
      "titleView": { "type": "(user: CometChat.User) => ReactNode", "default": "undefined" },
      "subtitleView": { "type": "(user: CometChat.User) => ReactNode", "default": "undefined" },
      "trailingView": { "type": "(user: CometChat.User) => ReactNode", "default": "undefined" },
      "itemView": { "type": "(user: CometChat.User) => ReactNode", "default": "undefined" },
      "headerView": { "type": "ReactNode", "default": "undefined" },
      "loadingView": { "type": "ReactNode", "default": "undefined" },
      "errorView": { "type": "ReactNode", "default": "undefined" },
      "emptyView": { "type": "ReactNode", "default": "undefined" }
    }
  },
  "events": [],
  "sdkListeners": ["onUserOnline", "onUserOffline", "onConnected"],
  "types": {
    "CometChatUsersSelectionMode": "'none' | 'single' | 'multiple'",
    "CometChatUserOption": "{ id: string; title: string; iconURL?: string; onClick: (user: CometChat.User) => void }",
    "CometChatFetchState": "'idle' | 'loading' | 'loaded' | 'error' | 'empty'"
  }
}

Where It Fits

CometChatUsers is a feature component that fetches and displays a paginated list of CometChat users. Wire it to CometChatMessageList via the onItemClick callback to build a one-to-one chat interface — selecting a user loads the conversation in the message pane.
import { useState } from "react";
import { CometChat } from "@cometchat/chat-sdk-javascript";
import { CometChatUsers, CometChatMessageList } from "@cometchat/chat-uikit-react";
import "@cometchat/chat-uikit-react/css-variables.css";

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

  return (
    <div style={{ display: "flex", height: "100vh" }}>
      <CometChatUsers onItemClick={setSelectedUser} activeUser={selectedUser ?? undefined} />
      {selectedUser && <CometChatMessageList user={selectedUser} />}
    </div>
  );
}

Minimal Render

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

function Demo() {
  return <CometChatUsers />;
}
Root CSS class: .cometchat-users

Usage Modes

CometChatUsers supports two modes: a Flat API for quick setup and a Compound API for full layout control.

Flat API

Pass all props directly to <CometChatUsers />. The component renders its default layout (header, search bar, list, state indicators) with your customizations applied:
import { CometChatUsers } from "@cometchat/chat-uikit-react";
import "@cometchat/chat-uikit-react/css-variables.css";

function Demo() {
  return (
    <CometChatUsers
      onItemClick={(user) => console.log("Selected:", user.getName())}
      subtitleView={(user) => <span>{user.getStatus()}</span>}
      trailingView={(user) => <button>Chat</button>}
    />
  );
}

Compound API

Use CometChatUsers.Root with sub-components for full control over layout and which pieces render. Omit a sub-component to hide it — no boolean props needed:
import { CometChatUsers } from "@cometchat/chat-uikit-react";
import "@cometchat/chat-uikit-react/css-variables.css";

function Demo() {
  return (
    <CometChatUsers.Root selectionMode="multiple" onSelect={handleSelect}>
      <CometChatUsers.Header />
      <CometChatUsers.SearchBar />
      <CometChatUsers.LoadingState />
      <CometChatUsers.ErrorState />
      <CometChatUsers.EmptyState />
      <CometChatUsers.List />
      <CometChatUsers.SelectedPreview />
    </CometChatUsers.Root>
  );
}
State sub-components (LoadingState, ErrorState, EmptyState) are self-managing — they read fetchState from context and automatically show/hide themselves. Place them all in the tree without conditional rendering.

Sub-Components

ComponentDescription
CometChatUsers.RootCalls the data hook, provides context, renders default layout when no children passed.
CometChatUsers.HeaderHeader with title text. Accepts optional title and children props.
CometChatUsers.SearchBarDebounced search input (300ms). Accepts optional placeholder prop.
CometChatUsers.ListUser list with infinite scroll. Only renders when users are available.
CometChatUsers.ItemIndividual user row (avatar, name, status, selection control).
CometChatUsers.SectionHeaderAlphabetical section divider (e.g., “A”, “B”).
CometChatUsers.EmptyStateRenders when fetchState === 'empty'. Pass children for custom content.
CometChatUsers.ErrorStateRenders when fetchState === 'error'. Pass children for custom content.
CometChatUsers.LoadingStateRenders when fetchState === 'loading'. Pass children for custom shimmer.
CometChatUsers.SelectedPreviewChips showing selected users (visible in multiple selection mode).

Filtering Users

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

const builder = new CometChat.UsersRequestBuilder()
  .setLimit(50)
  .setRoles(["admin", "moderator"]);

function AdminUsers() {
  return <CometChatUsers requestBuilder={builder} />;
}

Filter Recipes

RecipeCode
Limit to 50 users per pagenew CometChat.UsersRequestBuilder().setLimit(50)
Only friendsnew CometChat.UsersRequestBuilder().friendsOnly(true)
Filter by rolenew CometChat.UsersRequestBuilder().setRoles(["admin"])
Filter by statusnew CometChat.UsersRequestBuilder().setStatus("online")
Search by keywordnew CometChat.UsersRequestBuilder().setSearchKeyword("john")

Search Request Builder

Use searchRequestBuilder to customize the search behavior independently from the initial fetch:
import { CometChat } from "@cometchat/chat-sdk-javascript";
import { CometChatUsers } from "@cometchat/chat-uikit-react";
import "@cometchat/chat-uikit-react/css-variables.css";

const searchBuilder = new CometChat.UsersRequestBuilder()
  .setLimit(20)
  .setRoles(["admin"]);

function Demo() {
  return <CometChatUsers searchRequestBuilder={searchBuilder} />;
}

Actions and Events

Callback Props

onItemClick

Fires when a user item is clicked (in selectionMode: 'none'). Use this to drive navigation or load a conversation:
import { CometChat } from "@cometchat/chat-sdk-javascript";
import { CometChatUsers } from "@cometchat/chat-uikit-react";
import "@cometchat/chat-uikit-react/css-variables.css";

function Demo() {
  const handleUserClick = (user: CometChat.User) => {
    console.log("Navigate to chat with:", user.getName());
  };

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

onSelect

Fires when a user is selected or deselected (in single or multiple selection mode):
import { CometChat } from "@cometchat/chat-sdk-javascript";
import { CometChatUsers } from "@cometchat/chat-uikit-react";
import "@cometchat/chat-uikit-react/css-variables.css";

function Demo() {
  const handleSelect = (user: CometChat.User, selected: boolean) => {
    console.log(user.getName(), selected ? "selected" : "deselected");
  };

  return <CometChatUsers selectionMode="multiple" onSelect={handleSelect} />;
}

onError

Fires when an SDK fetch or listener error occurs. Use for logging or toast notifications:
import { CometChatUsers } from "@cometchat/chat-uikit-react";
import "@cometchat/chat-uikit-react/css-variables.css";

function Demo() {
  return (
    <CometChatUsers
      onError={(error) => console.error("Users fetch failed:", error)}
    />
  );
}

onEmpty

Fires when the initial fetch returns zero users:
import { CometChatUsers } from "@cometchat/chat-uikit-react";
import "@cometchat/chat-uikit-react/css-variables.css";

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

SDK Events (Real-Time, Automatic)

CometChatUsers automatically subscribes to SDK listeners for real-time updates. No manual setup required.
SDK ListenerInternal Behavior
onUserOnlineUpdates user status indicator to online
onUserOfflineUpdates user status indicator to offline
onConnectedRe-initializes the request builder and re-fetches from the beginning
In React 18 StrictMode, useEffect runs twice on mount in development. The component handles this gracefully by using unique listener IDs per instance and cleaning up on unmount.

Custom View Slots

SlotSignatureReplaces
itemView(user: CometChat.User) => ReactNodeEntire list item row
leadingView(user: CometChat.User) => ReactNodeAvatar
titleView(user: CometChat.User) => ReactNodeUser name
subtitleView(user: CometChat.User) => ReactNodeStatus text
trailingView(user: CometChat.User) => ReactNodeSelection control / trailing content
headerViewReactNodeDefault header
loadingViewReactNodeDefault shimmer
errorViewReactNodeDefault error message
emptyViewReactNodeDefault empty message

subtitleView

Add custom subtitle content below the user name:
import { CometChat } from "@cometchat/chat-sdk-javascript";
import { CometChatUsers } from "@cometchat/chat-uikit-react";
import "@cometchat/chat-uikit-react/css-variables.css";

function Demo() {
  return (
    <CometChatUsers
      subtitleView={(user: CometChat.User) => (
        <span style={{ color: user.getStatus() === "online" ? "green" : "gray" }}>
          {user.getStatus()}
        </span>
      )}
    />
  );
}

itemView

Replace the entire item row with a custom component:
import { CometChat } from "@cometchat/chat-sdk-javascript";
import { CometChatUsers } from "@cometchat/chat-uikit-react";
import "@cometchat/chat-uikit-react/css-variables.css";

function Demo() {
  return (
    <CometChatUsers
      itemView={(user: CometChat.User) => (
        <div style={{ display: "flex", alignItems: "center", padding: "8px 16px", gap: "12px" }}>
          <img
            src={user.getAvatar()}
            alt={user.getName()}
            width={40}
            height={40}
            style={{ borderRadius: "50%" }}
            loading="lazy"
            decoding="async"
          />
          <div>
            <strong>{user.getName()}</strong>
            <p style={{ margin: 0, fontSize: "12px", color: "#666" }}>{user.getRole()}</p>
          </div>
        </div>
      )}
    />
  );
}

Custom States (Compound API)

With the compound API, pass custom content as children to state sub-components:
import { CometChatUsers } from "@cometchat/chat-uikit-react";
import "@cometchat/chat-uikit-react/css-variables.css";

function Demo() {
  return (
    <CometChatUsers.Root>
      <CometChatUsers.Header />
      <CometChatUsers.SearchBar />
      <CometChatUsers.LoadingState>
        <div style={{ padding: "20px", textAlign: "center" }}>Loading users...</div>
      </CometChatUsers.LoadingState>
      <CometChatUsers.ErrorState>
        <div style={{ padding: "20px", textAlign: "center", color: "red" }}>
          Something went wrong. Please try again.
        </div>
      </CometChatUsers.ErrorState>
      <CometChatUsers.EmptyState>
        <div style={{ padding: "20px", textAlign: "center" }}>No users found.</div>
      </CometChatUsers.EmptyState>
      <CometChatUsers.List />
    </CometChatUsers.Root>
  );
}

Common Patterns

Sibling Communication (Users → Messages)

Drive a message list from user selection using parent state and the onItemClick callback:
import { useState } from "react";
import { CometChat } from "@cometchat/chat-sdk-javascript";
import { CometChatUsers, CometChatMessageList } from "@cometchat/chat-uikit-react";
import "@cometchat/chat-uikit-react/css-variables.css";

function ChatApp() {
  const [activeUser, setActiveUser] = useState<CometChat.User | null>(null);

  return (
    <div style={{ display: "flex", height: "100vh" }}>
      <div style={{ width: "320px", borderRight: "1px solid #eee" }}>
        <CometChatUsers
          onItemClick={setActiveUser}
          activeUser={activeUser ?? undefined}
        />
      </div>
      <div style={{ flex: 1 }}>
        {activeUser && <CometChatMessageList user={activeUser} />}
      </div>
    </div>
  );
}

Multiple Selection with Submit

Collect selected users and submit them (e.g., for creating a group):
import { useState } from "react";
import { CometChat } from "@cometchat/chat-sdk-javascript";
import { CometChatUsers, useCometChatUsersContext } from "@cometchat/chat-uikit-react";
import "@cometchat/chat-uikit-react/css-variables.css";

function SubmitButton() {
  const { selectedUsersMap } = useCometChatUsersContext();
  const selectedUsers = Array.from(selectedUsersMap.values());

  return (
    <button
      disabled={selectedUsers.length === 0}
      onClick={() => console.log("Create group with:", selectedUsers.map(u => u.getName()))}
    >
      Create Group ({selectedUsers.length})
    </button>
  );
}

function GroupCreator() {
  return (
    <CometChatUsers.Root selectionMode="multiple">
      <CometChatUsers.Header />
      <CometChatUsers.SearchBar />
      <CometChatUsers.LoadingState />
      <CometChatUsers.ErrorState />
      <CometChatUsers.EmptyState />
      <CometChatUsers.List />
      <CometChatUsers.SelectedPreview />
      <SubmitButton />
    </CometChatUsers.Root>
  );
}

Context Hook

Access user list state from any child rendered inside CometChatUsers.Root:
import { useCometChatUsersContext } from "@cometchat/chat-uikit-react";

function UserCount() {
  const { users, fetchState } = useCometChatUsersContext();

  if (fetchState !== "loaded") return null;
  return <span>{users.length} users loaded</span>;
}

CSS Architecture

The component uses CSS custom properties (design tokens) defined in @cometchat/chat-uikit-react/css-variables.css. The cascade:
  1. Global tokens set on the .cometchat root wrapper.
  2. Component CSS (.cometchat-users) consumes these tokens via var().
  3. Overrides target .cometchat-users descendant selectors.

Key Selectors

TargetSelector
Root container.cometchat-users
Header.cometchat-users__header
Search bar.cometchat-users__search-bar
List container.cometchat-users__list
User item.cometchat-users__item
Section header.cometchat-users__section-header
Empty state.cometchat-users__empty-state
Error state.cometchat-users__error-state
Loading state.cometchat-users__loading-state
Selected preview.cometchat-users__selected-preview

Example: Brand-themed users list

App.css
.cometchat-users {
  --cometchat-primary-color: #6851d6;
  --cometchat-background-color-01: #fafafa;
  --cometchat-text-color-primary: #1a1a1a;
  --cometchat-text-color-secondary: #666666;
  --cometchat-success-color: #22c55e;
}

.cometchat-users__item:hover {
  background-color: #f0ecfb;
}

Customization Matrix

What to changeWhereProperty/APIExample
Override behaviorComponent propsonItemClick, onSelect, onError callbacksonItemClick={(user) => navigate(user)}
Filter dataComponent propsrequestBuilderBuilder with .setRoles(["admin"])
Toggle UI elementsCompound APIOmit sub-componentRemove <SearchBar /> to hide search
Replace UI sectionsFlat API propsheaderView, emptyView, loadingViewemptyView={<Custom />}
Change visual stylingGlobal CSS.cometchat-users selectorsSee CSS example above

Props

All props are optional unless noted otherwise.

requestBuilder

Custom request builder for fetching users. Controls pagination, filtering, and sorting.
TypeCometChat.UsersRequestBuilder
DefaultInternal builder with limit 30

searchRequestBuilder

Custom request builder used specifically for search queries. When the user types in the search bar, this builder is used instead of requestBuilder.
TypeCometChat.UsersRequestBuilder
Defaultundefined

searchKeyword

Initial search keyword to pre-filter the user list on mount.
Typestring
Default""

hideUserStatus

Hide the online/offline status indicator dot on user items.
Typeboolean
Defaultfalse

selectionMode

Controls selection behavior and the UI controls shown on each item.
Type'none' | 'single' | 'multiple'
Default'none'
  • 'none': No selection controls. Clicking triggers onItemClick.
  • 'single': Radio buttons appear. One user selectable at a time.
  • 'multiple': Checkboxes appear. Supports shift-click range selection.

activeUser

The currently highlighted user. The matching item receives an active visual state.
TypeCometChat.User
Defaultundefined

sectionHeaderKey

The property used to extract alphabetical section headers from each user object.
Typekeyof CometChat.User
Default'getName'

options

Function that returns context menu options for each user. Options appear on hover/long-press.
Type(user: CometChat.User) => CometChatUserOption[]
Defaultundefined
interface CometChatUserOption {
  id: string;
  title: string;
  iconURL?: string;
  onClick: (user: CometChat.User) => void;
}

onItemClick

Callback when a user item is clicked (only fires in selectionMode: 'none'). Use for sibling component communication.
Type(user: CometChat.User) => void
Defaultundefined

onSelect

Callback when a user is selected or deselected (fires in single or multiple mode).
Type(user: CometChat.User, selected: boolean) => void
Defaultundefined

onError

Callback when an error occurs during fetch or real-time listener operations.
Type(error: unknown) => void
Defaultundefined

onEmpty

Callback when the initial fetch returns zero users.
Type() => void
Defaultundefined

showScrollbar

Whether to show the native scrollbar on the list. When false, the scrollbar is hidden via CSS but scrolling still works.
Typeboolean
Defaultfalse

leadingView

Custom leading view per user item. Replaces the default avatar.
Type(user: CometChat.User) => ReactNode
Defaultundefined

titleView

Custom title view per user item. Replaces the user name.
Type(user: CometChat.User) => ReactNode
Defaultundefined

subtitleView

Custom subtitle view per user item. Renders below the title.
Type(user: CometChat.User) => ReactNode
Defaultundefined

trailingView

Custom trailing view per user item. Replaces the selection control in selection modes.
Type(user: CometChat.User) => ReactNode
Defaultundefined

itemView

Fully custom item renderer. Overrides leadingView, titleView, subtitleView, and trailingView.
Type(user: CometChat.User) => ReactNode
Defaultundefined

headerView

Custom header content. Replaces the default header entirely.
TypeReactNode
Defaultundefined

loadingView

Custom loading state content. Replaces the default shimmer animation.
TypeReactNode
Defaultundefined

errorView

Custom error state content. Replaces the default error message.
TypeReactNode
Defaultundefined

emptyView

Custom empty state content. Replaces the default “no users” message.
TypeReactNode
Defaultundefined

CSS Selectors

TargetSelector
Root.cometchat-users
Header.cometchat-users__header
Header title.cometchat-users__header-title
Search bar.cometchat-users__search-bar
List.cometchat-users__list
Item.cometchat-users__item
Item (active).cometchat-users__item--active
Item avatar.cometchat-users__item-avatar
Item name.cometchat-users__item-name
Item status.cometchat-users__item-status
Section header.cometchat-users__section-header
Empty state.cometchat-users__empty-state
Error state.cometchat-users__error-state
Loading state.cometchat-users__loading-state
Selected preview.cometchat-users__selected-preview
Selected chip.cometchat-users__selected-chip

Accessibility

  • List container: role="listbox" with aria-label="Users list"
  • User items: role="option" with aria-selected
  • Section headers: role="separator" with aria-label
  • Loading state: aria-busy="true"
  • Keyboard: Tab to focus, ArrowUp/ArrowDown to navigate, Enter/Space to select, Escape to clear search
  • All icon-only buttons have aria-label
  • :focus-visible styles on all interactive elements