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

# Pinned Messages

> Display the messages pinned in a conversation, with unpin, save, copy, share and info actions.

<Accordion title="AI Integration Quick Reference">
  ```json theme={null}
  {
    "component": "CometChatPinnedMessages",
    "package": "@cometchat/chat-uikit-react-native",
    "import": "import { CometChatPinnedMessages } from \"@cometchat/chat-uikit-react-native\";",
    "description": "Lists the messages pinned in a conversation, newest pin first. A pin is conversation-wide and visible to everyone.",
    "requires": {
      "dashboardFlag": "Pin Messages must be enabled for your app in the CometChat Dashboard",
      "resolution": "The kit reads the flag at login and re-reads it on every reconnection — no app code required"
    },
    "props": {
      "data": {
        "user": { "type": "CometChat.User", "default": "undefined", "note": "Scopes the panel to a one-on-one conversation. Mutually exclusive with group" },
        "group": { "type": "CometChat.Group", "default": "undefined", "note": "Scopes the panel to a group. Mutually exclusive with user" },
        "limit": { "type": "number", "default": 30, "note": "Page size for the fetch; the SDK caps it at 100" }
      },
      "callbacks": {
        "onBack": "() => void",
        "onItemPress": "(message: CometChat.BaseMessage) => void"
      },
      "visibility": {
        "hideUnpinMessageOption": { "type": "boolean", "default": false },
        "hideSaveMessageOption": { "type": "boolean", "default": false },
        "hideUnsaveMessageOption": { "type": "boolean", "default": false },
        "hideCopyMessageOption": { "type": "boolean", "default": false },
        "hideShareMessageOption": { "type": "boolean", "default": false },
        "hideMessageInfoOption": { "type": "boolean", "default": false }
      },
      "customization": {
        "ItemView": "(message: CometChat.BaseMessage) => JSX.Element",
        "title": { "type": "string", "default": "localized" },
        "style": "DeepPartial<PinnedMessagesStyle>"
      }
    }
  }
  ```
</Accordion>

`CometChatPinnedMessages` lists the messages pinned in one conversation, newest pin first. A pin is
conversation-wide and visible to everyone, so this panel shows the same set to every participant.

<Warning>
  **Pin Messages must be enabled for your app in the CometChat Dashboard.** Until it is, the pin
  options never render and this panel has nothing to show. The UI Kit reads that flag itself at
  login and on every reconnect — there is no app code to write.
</Warning>

## Where It Fits

Open it from the message header or an overflow menu, scoped to the conversation the user is in. It is
a full-screen panel with its own back affordance rather than an inline strip.

<Frame>
  <img src="https://mintcdn.com/cometchat-22654f5b-feat-rn-pin-save-thread-subscription-uik/Ot3kMQMhbSdXXHRn/images/pin.png?fit=max&auto=format&n=Ot3kMQMhbSdXXHRn&q=85&s=a40f8fba9c8188f0ae6144a6ae9bd7a4" alt="The Pinned Messages screen: a titled screen with a back arrow, listing the pinned messages of one conversation as full bubbles grouped by sender and date. Each bubble carries a pin glyph beside its timestamp, and a media message shows its image with the caption beneath." width="2880" height="1666" data-path="images/pin.png" />
</Frame>

## Minimal Render

Pass **exactly one** of `user` or `group` — the panel is scoped to a single conversation.

<Tabs>
  <Tab title="TypeScript (User)">
    ```tsx theme={null}
    import { CometChatPinnedMessages } from "@cometchat/chat-uikit-react-native";

    <CometChatPinnedMessages
      user={user}
      onBack={() => navigation.goBack()}
      onItemPress={(message: CometChat.BaseMessage) => scrollToMessage(message)}
    />
    ```
  </Tab>

  <Tab title="TypeScript (Group)">
    ```tsx theme={null}
    import { CometChatPinnedMessages } from "@cometchat/chat-uikit-react-native";

    <CometChatPinnedMessages
      group={group}
      onBack={() => navigation.goBack()}
      onItemPress={(message: CometChat.BaseMessage) => scrollToMessage(message)}
    />
    ```
  </Tab>
</Tabs>

## Actions and Events

### Callback Props

#### onItemPress

Fires when a pinned row is tapped. The panel does not navigate for you — use it to close the panel and jump your message list to that message.

```tsx lines theme={null}
import { CometChatPinnedMessages } from "@cometchat/chat-uikit-react-native";
import { CometChat } from "@cometchat/chat-sdk-react-native";

function PinnedWithJump({ group }: { group: CometChat.Group }) {
  const handleItemPress = (message: CometChat.BaseMessage) => {
    navigation.goBack();
    scrollToMessageId(message.getId());
  };

  return <CometChatPinnedMessages group={group} onItemPress={handleItemPress} />;
}
```

#### onBack

Fires when the back affordance in the header is pressed.

```tsx lines theme={null}
<CometChatPinnedMessages group={group} onBack={() => navigation.goBack()} />
```

### Events

The panel keeps itself current from the kit's event bus, so a pin made anywhere — this screen, the message list, or another participant's device — lands here without a manual refresh.

| Event                                   | Fires when                                                      |
| --------------------------------------- | --------------------------------------------------------------- |
| `ccMessagePinned` / `ccMessageUnpinned` | This device pinned or unpinned.                                 |
| `ccMessageSaved` / `ccMessageUnsaved`   | This device saved or unsaved.                                   |
| `onMessagePinned` / `onMessageUnpinned` | Another participant pinned or unpinned — broadcast to everyone. |
| `onMessageSaved` / `onMessageUnsaved`   | The same user saved on another device — private multi-device.   |

<Note>
  **Removing asks, adding does not.** Unpin and Unsave show a confirmation; Pin and Save run
  immediately. This is deliberate and consistent across all CometChat UI Kits — the additive action
  has its own undo one tap away, the destructive one does not.
</Note>

***

## Opening from the Message Header

`CometChatMessageHeader` can raise the entry point for you. Set `showPinnedMessagesButton` and handle `onPinnedMessagesPress`.

<Note>
  Despite the name, this is **not a standalone button**. It adds a localized **"Pinned Messages" item
  to the header's `⋮` overflow menu**, alongside anything your own `options` prop contributes. On a
  header with no other menu items, turning it on is what makes the `⋮` appear at all.
</Note>

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

function Messages({ user, group }) {
  return (
    <>
      <CometChatMessageHeader
        user={user}
        group={group}
        showPinnedMessagesButton={true}
        onPinnedMessagesPress={() =>
          navigation.navigate("PinnedMessages", { user, group })
        }
      />
      <CometChatMessageList user={user} group={group} />
    </>
  );
}
```

<Warning>
  **Both props are required.** `showPinnedMessagesButton={true}` on its own does nothing — the menu
  item is only added when `onPinnedMessagesPress` is also supplied, and there is no warning when it
  is missing.
</Warning>

***

## Custom View Slots

| Slot       | Signature                                         | Replaces                                   |
| ---------- | ------------------------------------------------- | ------------------------------------------ |
| `ItemView` | `(message: CometChat.BaseMessage) => JSX.Element` | Entire pinned row — sender line and bubble |

The empty, error and loading states are not view slots on this component. Restyle them through `style.emptyStateStyle` and `style.errorStateStyle` instead — see [Styling](#styling).

### ItemView

Replace the whole row, including the sender line above the bubble.

```tsx lines theme={null}
import { CometChatPinnedMessages, useTheme } from "@cometchat/chat-uikit-react-native";
import { CometChat } from "@cometchat/chat-sdk-react-native";
import { View, Text } from "react-native";

function CustomPinnedRow({ group }: { group: CometChat.Group }) {
  const theme = useTheme();

  const getItemView = (message: CometChat.BaseMessage) => (
    <View
      style={{
        paddingHorizontal: 16,
        paddingVertical: 12,
        borderLeftWidth: 3,
        borderLeftColor: theme.color.primary,
      }}>
      <Text style={{ ...theme.typography.body.medium, color: theme.color.textPrimary }}>
        {message.getSender()?.getName()}
      </Text>
      <Text style={{ ...theme.typography.caption1.regular, color: theme.color.textSecondary }}>
        {(message as CometChat.TextMessage).getText?.()}
      </Text>
    </View>
  );

  return <CometChatPinnedMessages group={group} ItemView={getItemView} />;
}
```

***

## Common Patterns

### Read-only panel

Hide every mutating action and leave the panel as a reference list.

```tsx lines theme={null}
<CometChatPinnedMessages
  group={group}
  hideUnpinMessageOption
  hideSaveMessageOption
  hideUnsaveMessageOption
/>
```

### A custom title and close icon

```tsx lines theme={null}
<CometChatPinnedMessages
  group={group}
  title="Highlights"
  style={{ closeButtonIcon: require("./assets/chevron-left.png") }}
/>
```

***

## Styling

The component uses the theme system from `CometChatThemeProvider`. Pass a `style` prop to customize the appearance. Every default value resolves from a semantic theme token, so retheming the kit restyles this panel without touching it.

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

function StyledPinnedMessages({ group }) {
  return (
    <CometChatPinnedMessages
      group={group}
      style={{
        containerStyle: {
          backgroundColor: "#FEEDE1",
        },
        titleStyle: {
          color: "#F76808",
        },
        itemStyle: {
          senderNameStyle: {
            color: "#F76808",
          },
          avatarStyle: {
            containerStyle: {
              borderRadius: 8,
            },
          },
        },
      }}
    />
  );
}
```

### Style Properties

| Property               | Type                                 | Description                                                  |
| ---------------------- | ------------------------------------ | ------------------------------------------------------------ |
| `containerStyle`       | `ViewStyle`                          | Root container                                               |
| `headerContainerStyle` | `ViewStyle`                          | Header row holding the back control and title                |
| `titleStyle`           | `TextStyle`                          | Header title text                                            |
| `closeButtonIconStyle` | `ImageStyle`                         | Size and tint of the back control                            |
| `closeButtonIcon`      | `ImageSourcePropType \| JSX.Element` | Replaces the back icon itself                                |
| `itemStyle`            | `object`                             | One pinned row — see below                                   |
| `emptyStateStyle`      | `object`                             | `containerStyle`, `titleStyle`, `subTitleStyle`, `iconStyle` |
| `errorStateStyle`      | `object`                             | `containerStyle`, `titleStyle`, `subTitleStyle`, `iconStyle` |

`itemStyle` keys:

| Property                       | Type         | Description                                                           |
| ------------------------------ | ------------ | --------------------------------------------------------------------- |
| `containerStyle`               | `ViewStyle`  | The row                                                               |
| `headerContainerStyle`         | `ViewStyle`  | Avatar + sender name + date line above the bubble                     |
| `avatarStyle`                  | `object`     | Sender avatar                                                         |
| `senderNameStyle`              | `TextStyle`  | Sender name                                                           |
| `separatorStyle`               | `TextStyle`  | Divider between sender name and date                                  |
| `dateStyle`                    | `object`     | Pin timestamp                                                         |
| `savedIndicatorStyle`          | `ImageStyle` | Bookmark shown when a pinned message is **also** saved by this viewer |
| `savedIndicatorContainerStyle` | `ViewStyle`  | Wrapper around that bookmark                                          |
| `bubbleContainerStyle`         | `ViewStyle`  | Left inset that lines the bubble up under the sender name             |

***

## Props

Provide either `user` or `group`, not both. All other props are optional.

### user

Scopes the panel to a one-on-one conversation.

|         |                  |
| ------- | ---------------- |
| Type    | `CometChat.User` |
| Default | —                |

Mutually exclusive with `group`.

***

### group

Scopes the panel to a group conversation.

|         |                   |
| ------- | ----------------- |
| Type    | `CometChat.Group` |
| Default | —                 |

Mutually exclusive with `user`.

***

### limit

Page size for the fetch.

|         |          |
| ------- | -------- |
| Type    | `number` |
| Default | `30`     |

The server rejects a value above 100.

***

### onBack

Called when the back affordance is pressed.

|         |              |
| ------- | ------------ |
| Type    | `() => void` |
| Default | —            |

***

### onItemPress

Called when a row is pressed.

|         |                                            |
| ------- | ------------------------------------------ |
| Type    | `(message: CometChat.BaseMessage) => void` |
| Default | —                                          |

***

### hideUnpinMessageOption

Hides **Unpin** in the row's long-press menu.

|         |           |
| ------- | --------- |
| Type    | `boolean` |
| Default | `false`   |

***

### hideSaveMessageOption

Hides **Save** in the row's long-press menu.

|         |           |
| ------- | --------- |
| Type    | `boolean` |
| Default | `false`   |

***

### hideUnsaveMessageOption

Hides **Unsave** in the row's long-press menu.

|         |           |
| ------- | --------- |
| Type    | `boolean` |
| Default | `false`   |

***

### hideCopyMessageOption

Hides **Copy**.

|         |           |
| ------- | --------- |
| Type    | `boolean` |
| Default | `false`   |

***

### hideShareMessageOption

Hides **Share**.

|         |           |
| ------- | --------- |
| Type    | `boolean` |
| Default | `false`   |

***

### hideMessageInfoOption

Hides **Message Info**.

|         |           |
| ------- | --------- |
| Type    | `boolean` |
| Default | `false`   |

***

### ItemView

Replaces the default row entirely.

|         |                                                   |
| ------- | ------------------------------------------------- |
| Type    | `(message: CometChat.BaseMessage) => JSX.Element` |
| Default | —                                                 |

***

### title

Panel title.

|         |                             |
| ------- | --------------------------- |
| Type    | `string`                    |
| Default | Localized "Pinned Messages" |

***

### style

Per-instance style overrides, merged over the theme's `pinnedMessagesStyles`.

|         |                                    |
| ------- | ---------------------------------- |
| Type    | `DeepPartial<PinnedMessagesStyle>` |
| Default | —                                  |

See [Styling](#styling).

***

## Next Steps

<CardGroup cols={2}>
  <Card title="Saved Messages" icon="bookmark" href="/ui-kit/react-native/saved-messages">
    The private, cross-conversation counterpart
  </Card>

  <Card title="Message List" icon="comments" href="/ui-kit/react-native/message-list">
    Where the Pin and Save options are raised
  </Card>

  <Card title="Pin A Message (SDK)" icon="thumbtack" href="/sdk/react-native/pin-message">
    The SDK methods underneath this component
  </Card>

  <Card title="Events" icon="tower-broadcast" href="/ui-kit/react-native/events">
    Every UI Kit event, in one place
  </Card>
</CardGroup>
