> ## 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.

# Conversation List + Message View

> Build a two-panel conversation list + message view layout in React.js with CometChat UI Kit.

<Accordion title="AI Integration Quick Reference">
  | Field        | Value                                                                                                  |
  | ------------ | ------------------------------------------------------------------------------------------------------ |
  | Package      | `@cometchat/chat-uikit-react`                                                                          |
  | Framework    | React.js                                                                                               |
  | Components   | `CometChatConversations`, `CometChatMessageHeader`, `CometChatMessageList`, `CometChatMessageComposer` |
  | Layout       | Two-panel — conversation list (left) + message view (right)                                            |
  | Prerequisite | Complete [React.js Integration](/ui-kit/react/react-js-integration) Steps 1–5 first                    |
  | Pattern      | WhatsApp Web, Slack, Microsoft Teams                                                                   |
</Accordion>

This guide builds a two-panel chat layout — conversation list on the left, messages on the right. Users tap a conversation to open it.

This assumes you've already completed [React.js Integration](/ui-kit/react/react-js-integration) (project created, UI Kit installed, init + login working, CSS imported).

<Frame>
  <img src="https://mintcdn.com/cometchat-22654f5b/-YC7tOebleeoFejE/images/e6411d13-chat_experience_sidebar_message-35c431d8bf694e5690e4e0f3a74165af.png?fit=max&auto=format&n=-YC7tOebleeoFejE&q=85&s=03a9df5c80f787357ebc4508839a88cb" width="1282" height="802" data-path="images/e6411d13-chat_experience_sidebar_message-35c431d8bf694e5690e4e0f3a74165af.png" />
</Frame>

[<img src="https://mintcdn.com/cometchat-22654f5b/yTI4I4kRxoDgb1t-/images/30d34521-play-codesandbox.svg?fit=max&auto=format&n=yTI4I4kRxoDgb1t-&q=85&s=0f01bdcfd9001740f479687e70911c7c" width="165" height="32" data-path="images/30d34521-play-codesandbox.svg" />](https://link.cometchat.com/react-conversation-list-message)

> 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:

1. **Sidebar (conversation list)** — shows all active conversations (users and groups)
2. **Message view** — displays chat messages for the selected conversation in real time
3. **Message composer** — text input with support for media, emojis, and reactions

***

## Step 1 — Create the Sidebar Component

Create a `CometChatSelector` folder inside `src/`:

<Tree>
  <Tree.Folder name="src" defaultOpen>
    <Tree.Folder name="CometChatSelector" defaultOpen>
      <Tree.File name="CometChatSelector.tsx" />

      <Tree.File name="CometChatSelector.css" />
    </Tree.Folder>
  </Tree.Folder>
</Tree>

<Tabs>
  <Tab title="TypeScript">
    ```tsx title="CometChatSelector.tsx" lines theme={null}
    import { useEffect, useState } from "react";
    import {
      Conversation,
      Group,
      User,
      CometChat,
    } from "@cometchat/chat-sdk-javascript";
    import {
      CometChatConversations,
      CometChatUIKitLoginListener,
    } from "@cometchat/chat-uikit-react";
    import "./CometChatSelector.css";

    interface SelectorProps {
      onSelectorItemClicked?: (
        input: User | Group | Conversation,
        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 | undefined
      >();

      useEffect(() => {
        const user = CometChatUIKitLoginListener.getLoggedInUser();
        setLoggedInUser(user);
      }, []);

      return (
        <>
          {loggedInUser && (
            <CometChatConversations
              activeConversation={
                activeItem instanceof CometChat.Conversation
                  ? activeItem
                  : undefined
              }
              onItemClick={(e) => {
                setActiveItem(e);
                onSelectorItemClicked(e, "updateSelectedItem");
              }}
            />
          )}
        </>
      );
    };
    ```
  </Tab>

  <Tab title="CSS">
    ```css title="CometChatSelector.css" lines theme={null}
    /* 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: 212px;
      top: 40px !important;
      left: 172px !important;
    }

    /* Logged-in user section */
    #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;
    }

    /* Selector container */
    .cometchat-selector {
      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-selector__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-selector__tab-icon-active {
      display: flex;
      width: 32px;
      height: 32px;
      justify-content: center;
      align-items: center;
      -webkit-mask-size: contain;
      mask-size: contain;
      cursor: default;
      background: var(--cometchat-icon-color-highlight);
      -webkit-mask: url('./assets/chats.svg') no-repeat center;
      mask: url('./assets/chats.svg') no-repeat center;
    }

    .cometchat-selector__tab-text-active {
      text-align: center;
      font: var(--cometchat-font-caption1-medium, 500 12px Roboto);
      cursor: default;
      color: var(--cometchat-text-color-highlight);
    }
    ```
  </Tab>
</Tabs>

Key points about the sidebar:

* `CometChatUIKitLoginListener.getLoggedInUser()` checks for an active session — the component only renders if a user is logged in.
* `activeConversation` highlights the currently selected conversation in the list.
* `onItemClick` fires when a user taps a conversation, passing the `Conversation` object to the parent.

***

## Step 2 — Update App.tsx and App.css

Wire the sidebar and message components together in your main app file.

<Tabs>
  <Tab title="TypeScript">
    ```tsx title="App.tsx" lines theme={null}
    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);

      return (
        <div className="conversations-with-messages">
          {/* Sidebar — conversation 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);
                } else if (item instanceof CometChat.Group) {
                  setSelectedUser(undefined);
                  setSelectedGroup(item as CometChat.Group);
                } else {
                  setSelectedUser(undefined);
                  setSelectedGroup(undefined);
                }
              }}
            />
          </div>

          {/* Message view — header + messages + composer */}
          {selectedUser || selectedGroup ? (
            <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;
    ```
  </Tab>

  <Tab title="CSS">
    ```css title="App.css" lines theme={null}
    @import url("@cometchat/chat-uikit-react/css-variables.css");

    #root {
      text-align: center;
      width: 100vw;
      height: 100vh;
      background-color: #282c34;
    }

    /* Two-panel layout */
    .conversations-with-messages {
      display: flex;
      height: 100%;
      width: 100%;
      flex-direction: row;
    }

    /* Left panel — conversation list */
    .conversations-wrapper {
      height: 100vh;
      width: 480px;
      overflow: hidden;
      display: flex;
      flex-direction: column;
    }

    .conversations-wrapper > .cometchat {
      overflow: hidden;
    }

    /* Right panel — messages */
    .messages-wrapper {
      width: 100%;
      height: 100%;
      display: flex;
      flex-direction: column;
    }

    /* Empty state */
    .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;
    }
    ```
  </Tab>
</Tabs>

How it works:

* When a conversation is tapped, `onSelectorItemClicked` extracts the `User` or `Group` from the `Conversation` object.
* `selectedUser` / `selectedGroup` state drives which chat is displayed — pass either `user` or `group` to the message components, never both.
* The empty state shows until a conversation is selected.

***

## Step 3 — Run the Project

<Tabs>
  <Tab title="Vite">
    ```bash lines theme={null}
    npm run dev
    ```
  </Tab>

  <Tab title="Create React App">
    ```bash lines theme={null}
    npm start
    ```
  </Tab>
</Tabs>

You should see the conversation list on the left. Tap any conversation to load messages on the right.

***

## Next Steps

<CardGroup cols={2}>
  <Card title="Theming" icon="paintbrush" href="/ui-kit/react/theme">
    Customize colors, fonts, and styles to match your brand
  </Card>

  <Card title="Components Overview" icon="grid-2" href="/ui-kit/react/components-overview">
    Browse all prebuilt UI components
  </Card>

  <Card title="React.js Integration" icon="react" href="/ui-kit/react/react-js-integration">
    Back to the main setup guide
  </Card>

  <Card title="Core Features" icon="comments" href="/ui-kit/react/core-features">
    Chat features included out of the box
  </Card>
</CardGroup>
