> ## Documentation Index
> Fetch the complete documentation index at: https://cometchat-22654f5b-feature-react-native-sdk-quotedmessage-a.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Building A Conversation List + Message View

The **Conversation List + Message View** layout offers a seamless **two-panel chat interface**, commonly used in modern messaging applications like **WhatsApp Web, Slack, and Microsoft Teams**.

This design enables users to switch between conversations effortlessly while keeping the chat window open, ensuring a **smooth, real-time messaging experience**.

[<img src="https://mintcdn.com/cometchat-22654f5b-feature-react-native-sdk-quotedmessage-a/R-mrzo_AxVZMXils/images/30d34521-play-codesandbox.svg?fit=max&auto=format&n=R-mrzo_AxVZMXils&q=85&s=719f2f667589e0991584e435e7936741" width="165" height="32" data-path="images/30d34521-play-codesandbox.svg" />](https://link.cometchat.com/next-conversation-list-message)

> **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 Overview**

<Frame>
  <img src="https://mintcdn.com/cometchat-22654f5b-feature-react-native-sdk-quotedmessage-a/yDKVamMkf61gj3YR/images/e6411d13-chat_experience_sidebar_message-35c431d8bf694e5690e4e0f3a74165af.png?fit=max&auto=format&n=yDKVamMkf61gj3YR&q=85&s=88eee0c31093fa6085af41cb0aff08ab" width="1282" height="802" data-path="images/e6411d13-chat_experience_sidebar_message-35c431d8bf694e5690e4e0f3a74165af.png" />
</Frame>

This layout is structured into three key sections:

1. **Sidebar (Conversation List)** – Displays active conversations, including users and groups.
2. **Message View** – Shows chat messages for the selected conversation in real-time.
3. **Message Composer** – Provides an input field for typing and sending messages, along with support for media, emojis, and reactions.

***

## **Step-by-Step Guide**

### **Step 1: Create Sidebar**

Let's create the `Sidebar` component which will render different conversations.

#### **Folder Structure**

Create a `CometChatSelector` folder inside your `src/app` directory and add the following files:

```swift theme={null}
src/app/
│── CometChatSelector/
│   ├── CometChatSelector.tsx
│   ├── CometChatSelector.css
```

#### **Download the Icon**

These icons are available in the **CometChat UI Kit assets folder**. You can find them at:\
🔗 [GitHub Assets Folder](https://github.com/cometchat/cometchat-uikit-react/tree/v6/sample-app/src/assets)

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

    // Define props interface for component
    interface SelectorProps {
        onSelectorItemClicked?: (input: User | Group | Conversation, type: string) => void;
    }

    // CometChatSelector component definition
    export const CometChatSelector = (props: SelectorProps) => {
        const {
            onSelectorItemClicked = () => { }, // Default function if no prop is provided
        } = props;

        // State to store the currently logged-in user
        const [loggedInUser, setLoggedInUser] = useState<CometChat.User | null>();
        
        // State to track the currently selected item (conversation, user, group, or call)
        const [activeItem, setActiveItem] = useState<
            CometChat.Conversation | CometChat.User | CometChat.Group | CometChat.Call | undefined
        >();

        useEffect(() => {
            // Retrieve the logged-in user from CometChat's login listener
            let loggedInUser = CometChatUIKitLoginListener.getLoggedInUser();
            setLoggedInUser(loggedInUser);
        }, [CometChatUIKitLoginListener?.getLoggedInUser()]); // Dependency array to trigger effect when user changes

        return (
            <>
                {/* Render CometChatConversations only if a user is logged in */}
                {loggedInUser && (
                    <>
                        <CometChatConversations
                            activeConversation={activeItem instanceof CometChat.Conversation ? activeItem : undefined}
                            onItemClick={(e) => {
                                setActiveItem(e); // Update the selected item state
                                onSelectorItemClicked(e, "updateSelectedItem"); // Trigger callback with selected item
                            }}
                        />
                    </>
                )}
            </>
        );
    }; 
    ```
  </Tab>

  <Tab title="CSS">
    ```css CometChatSelector.css theme={null}
    /* Style for the icon in the header menu of the conversation list */
    .selector-wrapper .cometchat-conversations .cometchat-list__header-menu .cometchat-button__icon {
        background: var(--cometchat-icon-color-primary);
    }

    /* Change background color of icon on hover */
    .cometchat-conversations .cometchat-list__header-menu .cometchat-button__icon:hover {
        background: var(--cometchat-icon-color-highlight);
    }

    /* Remove the right border from the search bar */
    .cometchat-list__header-search-bar {
        border-right: none;
    }

    /* Align submenu items to the left */
    .cometchat .cometchat-menu-list__sub-menu-list-item {
        text-align: left;
    }

    /* Set specific width and positioning for submenu list */
    .cometchat .cometchat-conversations .cometchat-menu-list__sub-menu-list {
        width: 212px;
        top: 40px !important;
        left: 172px !important;
    }

    /* Style the logged-in user section with a bottom border */
    #logged-in-user {
        border-bottom: 2px solid var(--cometchat-border-color-default, #E8E8E8);
    }

    /* Prevent cursor interaction on logged-in user menu items */
    #logged-in-user .cometchat-menu-list__sub-menu-item-title,
    #logged-in-user .cometchat-menu-list__sub-menu-list-item {
        cursor: default;
    }

    /* Style for logout icon with error color */
    .cometchat-menu-list__sub-menu-list-item-icon-log-out {
        background-color: var(--cometchat-error-color, #F44649);
    }

    /* Style for logout text with error color */
    .cometchat-menu-list__sub-menu-item-title-log-out {
        color: var(--cometchat-error-color, #F44649);
    }

    /* Allow pointer interaction on submenu items inside chat menu */
    .chat-menu .cometchat .cometchat-menu-list__sub-menu-item-title {
        cursor: pointer;
    }

    /* Remove shadow from submenu inside chat menu */
    .chat-menu .cometchat .cometchat-menu-list__sub-menu {
        box-shadow: none;
    }

    /* Style for submenu icons inside chat menu */
    .chat-menu .cometchat .cometchat-menu-list__sub-menu-icon {
        background-color: var(--cometchat-icon-color-primary, #141414);
        width: 24px;
        height: 24px;
    }
    ```
  </Tab>
</Tabs>

### **Step 2: Render Experience**

Now we will create the `CometChatNoSSR.tsx` & `CometChatNoSSR.css` files. Here, we will initialize the CometChat UI Kit, log in a user, and build the messaging experience using `CometChatMessageHeader`, `CometChatMessageList`, and `CometChatMessageComposer` components.

```
src/
│── CometChatNoSSR/
│   ├── CometChatNoSSR.tsx
│   ├── CometChatNoSSR.css
```

<Tabs>
  <Tab title="TypeScript">
    ```tsx CometChatNoSSR.tsx theme={null}
    import React, { useEffect, useState } from "react";
    import { 
        CometChatMessageComposer, 
        CometChatMessageHeader, 
        CometChatMessageList, 
        CometChatUIKit, 
        UIKitSettingsBuilder 
    } from "@cometchat/chat-uikit-react";
    import { CometChat } from "@cometchat/chat-sdk-javascript";
    import { CometChatSelector } from "../CometChatSelector/CometChatSelector";
    import "./CometChatNoSSR.css";

    // Constants for CometChat configuration
    const COMETCHAT_CONSTANTS = {
      APP_ID: "",
      REGION: "",
      AUTH_KEY: "",
    };

    // Functional Component
    const CometChatNoSSR: React.FC = () => {
      // State to store the logged-in user
      const [user, setUser] = useState<CometChat.User | undefined>(undefined);
      // State to store selected user or group
      const [selectedUser, setSelectedUser] = useState<CometChat.User | undefined>(undefined);
      const [selectedGroup, setSelectedGroup] = useState<CometChat.Group | undefined>(undefined);

      useEffect(() => {
        // Initialize UIKit settings
        const UIKitSettings = new UIKitSettingsBuilder()
          .setAppId(COMETCHAT_CONSTANTS.APP_ID)
          .setRegion(COMETCHAT_CONSTANTS.REGION)
          .setAuthKey(COMETCHAT_CONSTANTS.AUTH_KEY)
          .subscribePresenceForAllUsers()
          .build();

        // Initialize CometChat UIKit
        CometChatUIKit.init(UIKitSettings)
          ?.then(() => {
            console.log("Initialization completed successfully");
            // Check if user is already logged in
            CometChatUIKit.getLoggedinUser().then((loggedInUser) => {
              if (!loggedInUser) {
                // Perform login if no user is logged in
                CometChatUIKit.login("cometchat-uid-1")
                  .then((user) => {
                    console.log("Login Successful", { user });
                    setUser(user);
                  })
                  .catch((error) => console.error("Login failed", error));
              } else {
                console.log("Already logged-in", { loggedInUser });
                setUser(loggedInUser);
              }
            });
          })
          .catch((error) => console.error("Initialization failed", error));
      }, []);

      return user ? (
        <div className="conversations-with-messages">
          {/* Sidebar with conversation list */}
          <div className="conversations-wrapper">
            <CometChatSelector 
              onSelectorItemClicked={(activeItem) => {
                let item = activeItem;
                // Extract the conversation participant
                if (activeItem instanceof CometChat.Conversation) {
                  item = activeItem.getConversationWith();
                }
                // Update states based on the type of selected item
                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 section */}
          {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 Conversation to start</div>
          )}
        </div>
      ) : undefined;
    };

    export default CometChatNoSSR;
    ```
  </Tab>

  <Tab title="CSS">
    ```css CometChatNoSSR.css theme={null}
    /* Layout for the main conversations and messages container */
    .conversations-with-messages {
        display: flex;
        height: 100%;
        width: 100%;
    }

    /* Sidebar wrapper for conversations */
    .conversations-wrapper {
        height: 100%;
        width: 480px; /* Fixed width for conversation list */
        overflow: hidden;
        display: flex;
        flex-direction: column;
        height: inherit;
    }

    /* Hide overflow for the conversation list */
    .conversations-wrapper > .cometchat {
        overflow: hidden;
    }

    /* Message section layout */
    .messages-wrapper {
        width: calc(100% - 480px); /* Take remaining space */
        height: 100%;
        display: flex;
        flex-direction: column;
    }

    /* Display styling for when no conversation is selected */
    .empty-conversation {
        height: 100%;
        width: 100%;
        display: flex;
        justify-content: center;
        align-items: center;
        background: white;
        color: var(--cometchat-text-color-secondary, #727272);
        font: var(--cometchat-font-body-regular, 400 14px Roboto);
    }

    /* Ensure message composer does not have rounded corners */
    .cometchat .cometchat-message-composer {
        border-radius: 0px;
    }
    ```
  </Tab>
</Tabs>

### **Step 3: Disabling SSR for `CometChatNoSSR.tsx` in Next.js**

In this update, we will **disable Server-Side Rendering (SSR) for `CometChatNoSSR.tsx`** while keeping the rest of the application’s SSR functionality intact. This ensures that the **CometChat UI Kit components load only on the client-side**, preventing SSR-related issues.

#### **Disabling SSR in `index.tsx`**

Modify your `index.tsx` file to dynamically import the `CometChatNoSSR.tsx` component with `{ ssr: false }`.

```tsx index.tsx theme={null}
import { Inter } from "next/font/google";
import dynamic from "next/dynamic";

import '@cometchat/chat-uikit-react/css-variables.css';

const inter = Inter({ subsets: ["latin"] });

// Dynamically import CometChat component with SSR disabled
const CometChatComponent = dynamic(() => import("../CometChatNoSSR/CometChatNoSSR"), {
  ssr: false,
});

export default function Home() {
  return <CometChatComponent />;
}
```

#### **Why disable SSR?**

* The CometChat UI Kit depends on browser APIs (window, document, WebSockets).
* Next.js pre-renders components on the server, which can cause errors with browser-specific features.
* By setting `{ ssr: false }`, we ensure that CometChatNoSSR.tsx only loads on the client.

### **Step 4: Update Global CSS**

Next, add the following styles to global.css to ensure CometChat UI Kit is properly styled.

```css global.css theme={null}
:root {
  --background: #ffffff;
  --foreground: #171717;
}

@media (prefers-color-scheme: dark) {
  :root {
    --background: #0a0a0a;
    --foreground: #ededed;
  }
}

/** Give your App a height of `100%`. Keep other CSS properties in the below selector as it is. */
.root {
  height: 100%;
}

#__next {
  height: 100%;
}

html,
body {
  height: 100%;
}

html,
body {
  max-width: 100vw;
  overflow-x: hidden;
}

body {
  color: var(--foreground);
  background: var(--background);
  font-family: Arial, Helvetica, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

* {
  box-sizing: border-box;
  padding: 0;
  margin: 0;
}

a {
  color: inherit;
  text-decoration: none;
}

@media (prefers-color-scheme: dark) {
  html {
    color-scheme: dark;
  }
}
```

### **Step 5: Run the project**

```
npm run dev
```

***

## **Next Steps**

### **Enhance the User Experience**

* **[Advanced Customizations](/ui-kit/react/theme)** – Personalize the chat UI to align with your brand.

***
