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

# Pin & Save Messages

> Let users pin important messages for everyone in a conversation and save messages privately for themselves.

## Goal

By the end of this guide you will have a chat screen where users can **pin** a message so it's highlighted for everyone in the conversation, open a panel of all pinned messages, and **save** a message privately to their own list — with a dedicated "Saved" screen to review saves across every conversation.

Pin and save are two separate concepts:

|                 | Pin                                          | Save                                         |
| --------------- | -------------------------------------------- | -------------------------------------------- |
| **Visible to**  | Everyone in the conversation                 | Only the current user                        |
| **Scope**       | One conversation                             | All conversations                            |
| **Surfaced by** | `CometChatPinnedMessages` (per conversation) | `CometChatSavedMessages` (a personal screen) |
| **Opened from** | The message header's pinned-messages action  | Your own navigation (no built-in trigger)    |

## Prerequisites

* Completed the [Integration Guide](/ui-kit/react/integration-react)
* A running `CometChatProvider` setup with valid credentials
* An existing chat screen using `CometChatMessageHeader`, `CometChatMessageList`, and `CometChatMessageComposer`
* **Pin messages** and **Save messages** enabled for your app through the `features.ux.messages.pinned.enabled` and `features.ux.messages.saved.enabled` app settings. See [Core Features → Pin & Save](/ui-kit/react/core-features#pin-and-save-messages).

<Note>
  The pin/unpin and save/unsave options only appear in the message options menu when the corresponding feature is enabled for your app. The UI Kit reads that setting at login, so no extra wiring is needed to show or hide the options.
</Note>

## Step 1: The Message Options

Once the features are enabled, `CometChatMessageList` automatically adds **Pin**, **Unpin**, **Save**, and **Unsave** to the message options menu — no props required. You only need the `hide*` props if you want to remove one:

*File: ChatScreen.tsx*

```tsx theme={null}
import { CometChatMessageList } from "@cometchat/chat-uikit-react";

<CometChatMessageList
  group={group}
  // Options are shown by default; pass hide* props only to remove them:
  // hidePinMessageOption
  // hideSaveMessageOption
/>
```

Who can pin is enforced by the SDK based on the conversation and the user's role (group owners, admins, and moderators can pin in a group). See the [Message List options](/ui-kit/react/components/message-list#pin-and-save-options).

## Step 2: Open the Pinned Messages Panel

`CometChatMessageHeader` exposes a pinned-messages action in its overflow menu. Wire `onPinnedMessagesClicked` to show `CometChatPinnedMessages`, scoped to the same `user`/`group`.

*File: ChatScreen.tsx*

```tsx theme={null}
import { useState } from "react";
import { CometChat } from "@cometchat/chat-sdk-javascript";
import {
  CometChatMessageHeader,
  CometChatMessageList,
  CometChatMessageComposer,
  CometChatPinnedMessages,
} from "@cometchat/chat-uikit-react";

function ChatScreen({ group }: { group: CometChat.Group }) {
  const [showPins, setShowPins] = useState(false);

  return (
    <div style={{ display: "flex", height: "100%" }}>
      <div style={{ flex: 1, display: "flex", flexDirection: "column" }}>
        <CometChatMessageHeader
          group={group}
          onPinnedMessagesClicked={() => setShowPins(true)}
        />
        <div style={{ flex: 1, overflow: "hidden" }}>
          <CometChatMessageList group={group} />
        </div>
        <CometChatMessageComposer group={group} />
      </div>

      {showPins && (
        <div style={{ width: "360px", borderLeft: "1px solid #e0e0e0" }}>
          <CometChatPinnedMessages
            group={group}
            onClose={() => setShowPins(false)}
            onItemClick={() => setShowPins(false)}
          />
        </div>
      )}
    </div>
  );
}
```

<Note>
  The pinned-messages action only appears in the header when pinning is enabled (the `features.ux.messages.pinned.enabled` app setting) **and** you provide `onPinnedMessagesClicked`. Use `hidePinnedMessagesOption` on the header to remove it explicitly.
</Note>

## Step 3: Add a "Saved" Screen

Saves are personal and span every conversation, so `CometChatSavedMessages` takes no `user`/`group` and is **not** opened from a built-in menu. Mount it wherever your app wants a "Saved" destination — a route, a tab, or a panel toggled from your own button.

*File: AppShell.tsx*

```tsx theme={null}
import { useState } from "react";
import { CometChatSavedMessages } from "@cometchat/chat-uikit-react";

function AppShell() {
  const [showSaved, setShowSaved] = useState(false);

  return (
    <>
      <button onClick={() => setShowSaved(true)}>Saved</button>

      {showSaved && (
        <CometChatSavedMessages onClose={() => setShowSaved(false)} />
      )}
    </>
  );
}
```

## Step 4: Pinned & Saved Indicators

Pinned and saved messages render an indicator on the bubble in the main message list, so users can see a message's status inline. This is automatic — no configuration needed. See [Message Bubble → Pinned & Saved indicators](/ui-kit/react/components/message-bubble#pinned-and-saved-indicators).

<Info>
  **Live Preview** — a bubble carrying both the pinned and saved indicators.

  [Open in Storybook ↗](https://storybook.cometchat.io/react/?path=/story/components-bubbles-message-bubble--pinned-and-saved)
</Info>

<iframe src="https://storybook.cometchat.io/react/iframe.html?id=components-bubbles-message-bubble--pinned-and-saved&viewMode=story&shortcuts=false&singleStory=true" className="w-full rounded-xl" loading="lazy" style={{height: "250px", border: "1px solid #e0e0e0"}} title="CometChat Message Bubble — Pinned & Saved" allow="clipboard-write" />

## Step 5: Limits

Your app can cap how many messages may be pinned or saved. These caps are configured as app settings in the dashboard:

| Setting                                | Caps                                                                                                            |
| -------------------------------------- | --------------------------------------------------------------------------------------------------------------- |
| features.ux.messages.pinned.limit      | Pins per conversation                                                                                           |
| features.ux.messages.saved.limit       | Saves per user                                                                                                  |
| features.ux.conversations.pinned.limit | Pinned conversations per user (see [Conversations](/ui-kit/react/components/conversations#hidepinconversation)) |

When a user hits a cap, the UI Kit shows a toast explaining the limit — you don't need to handle the error yourself. The kit reads these settings at login so the toast can name the exact cap.

## Complete Example

*File: App.tsx*

```tsx theme={null}
import { useState } from "react";
import { CometChat } from "@cometchat/chat-sdk-javascript";
import {
  CometChatProvider,
  CometChatConversations,
  CometChatMessageHeader,
  CometChatMessageList,
  CometChatMessageComposer,
  CometChatPinnedMessages,
  CometChatSavedMessages,
} from "@cometchat/chat-uikit-react";

function ChatWithPinSave() {
  const [user, setUser] = useState<CometChat.User | null>(null);
  const [group, setGroup] = useState<CometChat.Group | null>(null);
  const [showPins, setShowPins] = useState(false);
  const [showSaved, setShowSaved] = useState(false);

  function handleConversationClick(conversation: CometChat.Conversation) {
    setShowPins(false);
    const entity = conversation.getConversationWith();
    if (entity instanceof CometChat.User) {
      setUser(entity);
      setGroup(null);
    } else if (entity instanceof CometChat.Group) {
      setGroup(entity);
      setUser(null);
    }
  }

  return (
    <div style={{ display: "flex", height: "100vh" }}>
      {/* Conversations sidebar */}
      <div style={{ width: "300px", borderRight: "1px solid #e0e0e0", display: "flex", flexDirection: "column" }}>
        <button onClick={() => setShowSaved(true)}>Saved messages</button>
        <CometChatConversations onItemClick={handleConversationClick} />
      </div>

      {/* Main message panel */}
      <div style={{ flex: 1, display: "flex", flexDirection: "column" }}>
        {(user || group) && (
          <>
            <CometChatMessageHeader
              user={user ?? undefined}
              group={group ?? undefined}
              onPinnedMessagesClicked={() => setShowPins(true)}
            />
            <div style={{ flex: 1, overflow: "hidden" }}>
              <CometChatMessageList user={user ?? undefined} group={group ?? undefined} />
            </div>
            <CometChatMessageComposer user={user ?? undefined} group={group ?? undefined} />
          </>
        )}
      </div>

      {/* Pinned messages panel */}
      {showPins && (user || group) && (
        <div style={{ width: "360px", borderLeft: "1px solid #e0e0e0" }}>
          <CometChatPinnedMessages
            user={user ?? undefined}
            group={group ?? undefined}
            onClose={() => setShowPins(false)}
            onItemClick={() => setShowPins(false)}
          />
        </div>
      )}

      {/* Saved messages screen */}
      {showSaved && (
        <div style={{ width: "360px", borderLeft: "1px solid #e0e0e0" }}>
          <CometChatSavedMessages onClose={() => setShowSaved(false)} />
        </div>
      )}
    </div>
  );
}

function App() {
  return (
    <CometChatProvider>
      <ChatWithPinSave />
    </CometChatProvider>
  );
}

export default App;
```

## Next Steps

* [Pinned Messages](/ui-kit/react/components/pinned-messages) — configure the pinned-messages panel
* [Saved Messages](/ui-kit/react/components/saved-messages) — configure the saved-messages screen
* [Message List](/ui-kit/react/components/message-list) — toggle the pin/save message options
* [Conversations](/ui-kit/react/components/conversations#hidepinconversation) — let users pin whole conversations
