Skip to main content

Goal

By the end of this guide you will have a chat interface where users can open a thread panel from any message, view the parent message with its reply count, browse threaded replies, and send new replies — all using v7 compound components and a state-based approach (no custom events needed).

Prerequisites

  • Completed the Integration Guide guide
  • A running CometChatProvider setup with valid credentials
  • An existing chat screen using CometChatMessageList and CometChatMessageComposer

Components Used

Step 1: Thread State Management

Store the threadedMessage in state. When set, the thread panel renders. When cleared, it closes. This mirrors the pattern used in the sample app’s CometChatThreadPanel component. File: ChatWithThreads.tsx

Step 2: Wire the Thread Trigger

Use the onThreadRepliesClick callback on CometChatMessageList to capture when a user clicks “Reply in Thread.” This sets the threaded message and opens the panel — no events required. File: ChatWithThreads.tsx

Step 3: Build the Thread Panel

When threadedMessage is set, render a side panel composing CometChatThreadHeader + CometChatMessageList (with parentMessage) + CometChatMessageComposer (with parentMessageId, layout="compact", and enableRichTextEditor). The onClose callback clears the state to dismiss the panel. File: ChatWithThreads.tsx

Step 4: Handle Parent Deleted

Use the onParentDeleted prop on CometChatThreadHeader to automatically close the thread panel when the parent message is deleted by another user or a moderation action. File: ChatWithThreads.tsx

Complete Example

File: App.tsx

Thread Subscription

Users can subscribe to a thread to keep getting updates about new replies even when they aren’t actively viewing it, and unsubscribe to stop. This works in both 1:1 and group conversations. The UI Kit surfaces this in two places, both wired out of the box:
  • A bell toggle in CometChatThreadHeader.
  • A subscribe / unsubscribe option in the message context menu of CometChatMessageList.
Both reflect the current subscription state, flip it optimistically on click, and show a toast if the server rejects the change. No wiring is required to make them work.

Automatic subscription

Beyond the manual bell and menu option, the UI Kit subscribes a user to a thread automatically in a few cases, so people keep getting updates on threads they’re actually part of — without having to remember to follow them:
  • Sending a message subscribes you to its thread. When you send a message, you’re subscribed to the thread on that message — so you keep hearing about replies to it — and sending a reply inside a thread subscribes you to that thread as well. This applies to every message type — text, media, stickers, polls, collaborative documents, and custom messages.
  • Being @mentioned in a reply subscribes you. If someone @mentions you in a threaded reply, you’re subscribed — whether the mention is added on a fresh reply or introduced (or preserved) by an edit.
  • A reply from someone else that doesn’t mention you does not subscribe you. You’re only pulled in when you author something in the thread or you’re mentioned.
These rules apply in real time and across devices, and a change is mirrored to every surface — the bell in CometChatThreadHeader and the subscribe/unsubscribe option in CometChatMessageListwhether or not the thread panel is open. A deliberate unsubscribe is remembered and survives a reload, but sending another message in that thread, or being mentioned in it again, re-subscribes you. The labels and toasts are localizable — override the thread_subscription_subscribe, thread_subscription_unsubscribe, thread_subscription_subscribed_toast, thread_subscription_unsubscribed_toast, and thread_subscription_failed keys via localization.

Reacting to changes

Pass onThreadSubscriptionChange to the thread header to run your own logic when the user subscribes or unsubscribes:

Hiding the controls

Driving it yourself

For custom UI, the useThreadSubscription hook exposes the same state and toggle. Pass an optional second argument to react when the subscription flips (from the toggle here, or from any automatic or manual change elsewhere):
If you only need to read the state — for example, to render an indicator without a toggle — use useThreadSubscriptionState, which returns the boolean alone and stays in sync with every automatic and manual change:
Subscription changes are broadcast on the event bus as ui:thread/subscription-changed — the single channel every open surface (the bell, the option, your custom UI) listens to, so a flip anywhere is reflected everywhere.

Next Steps