Skip to main content
The CometChatPinnedMessages component lists every message pinned in a conversation, newest pin first. Pins are conversation-wide — everyone in the chat sees the same list — so the panel is a shared, always-current view of what the conversation has singled out.

Overview

The Pinned Messages panel provides:
  • Conversation-scoped list: Pass either a user or a group; the panel fetches that conversation’s pins
  • Real message bubbles: Each row renders the actual message bubble, so media, polls, and formatted text look as they do in the chat
  • Pinned-by attribution: Each row is labelled with who pinned it and when
  • Inline unpin: A per-row unpin control, behind a confirmation dialog
  • Row options: Save, Copy, Info, Translate, Report, and Message privately under a three-dot menu
  • Message information: Opens over the panel, without leaving it — Info is self-contained, so it is not forwarded to the host
  • System pins respected: A pin the app placed app-wide cannot be lifted by a member, so Unpin is withheld on those rows
  • Live updates: Edits, deletions, reactions, and pin changes are reflected without a refetch
  • Focus trap: Traps keyboard focus within the panel for modal-like behavior
Pin Message is gated by the features.ux.messages.pinned.enabled app setting, which CometChat provisions server-side. Until it is on, CometChat.isPinMessageEnabled() resolves false and the pin surfaces do not render. See Enabling Pin and Save for the development override.
Live Preview — a group conversation with several pinned messages, newest pin first. Open in Storybook ↗

Basic Usage

Group Pinned Messages

One-on-One Pinned Messages

Pass user instead of group. The two are mutually exclusive — set exactly one.

Opening the Panel from the Message Header

CometChatMessageHeader can add a Pinned messages entry to its overflow menu. The header only asks for the panel — the host decides where it appears.

Handling Forwarded Options

Unpin, Save, Unsave, Copy, and Message Information are completed by the panel itself. Translate, Report, and Message privately need surfaces the panel does not own — a translation cache, a report dialog, another conversation — so they are handed to the host rather than half-built here. Message privately also fires CometChatUIEvents.ccOpenChat, so a host already listening for that receives both.

Filtering

Pass a messagesRequestBuilder to control which pinned messages are fetched — the page size, most commonly. Call setPinned(true) on the builder: it is what scopes the request to pinned messages, and without it the request is an ordinary history read.
The component re-asserts setPinned(true) and the user / group conversation scope on whatever builder you pass, so those are safe even if you omit them — but keep setPinned(true) in your code to make the intent explicit. Do not set a different conversation scope on the builder.

Properties

Events

Behavior

Row Options

Options appear in a fixed order, and quickOptionsCount decides how many stay outside the ⋮: The list is read-only in every other respect: opening it marks nothing as read, moves no unread count, and nothing here edits or deletes a message.

Permissions

There is no client-side role gate. Unpin is offered to every member and the server is the sole authority — a member without the permission still sees the option, the call is refused with ERR_ACTION_NOT_ALLOWED, and the optimistic flip reverts with a toast. Unpin is deliberately not restricted to whoever pinned the message either — anyone the server allows can remove any pin.
[hideUnpinMessageOption]="true" is the only thing that withholds Unpin from the panel, apart from a system pin. Set it yourself where your app already knows the viewer cannot unpin; the panel will not work that out on its own.

System Pins

An app can pin a message itself, app-wide, rather than on behalf of a member. A system pin (pinnedBy === "app_system") belongs to no one, and the server refuses to lift it for any member — so Unpin is not offered on those rows at all, here or in the message list. Save is untouched: it is private to the viewer and has nothing to do with who pinned. System pins are capped separately from member pins, through the features.ux.messages.pinned.system.limit app setting.

Confirmation

Unpinning asks for confirmation; pinning does not. Pinning is trivially reversible and a dialog for it would only be friction, whereas unpinning removes something the whole conversation can see.

Rendering Large Lists

The pinned read is not cursor-paginated — the server ignores sentAt/id when filtering by pinned — so the panel fetches in one request (limit 100 unless messagesRequestBuilder says otherwise) and windows locally: it renders 30 rows at a time and extends the window as you scroll. A conversation with hundreds of pins does not pay to build every bubble up front.

Live Updates

The panel subscribes to CometChatPinSaveEvents, so a pin or unpin made anywhere — by another member, or by this user on another device — is reflected without a refetch. Edits, deletions, and reactions on a pinned message update its row in place.

Customization

CSS Variables

Accessibility

Keyboard Navigation

  • Escape dismisses the topmost layer only: the information overlay first, then the confirmation dialog, then the panel itself
  • Tab cycles within the panel; focus does not escape to the page behind it
  • Enter / Space on a row activates it, as a click does

Focus Management

Focus is trapped on open and released on destroy, so the panel behaves as a modal surface while it is up.

Screen Reader Support

  • The panel is a labelled region
  • Rows are exposed as buttons
  • Loading, empty, and error states are announced via role="status"
  • Decorative glyphs — pin markers, media icons, illustrations — are aria-hidden