diff --git a/docs.json b/docs.json index 62cbfe27b..07d060f50 100644 --- a/docs.json +++ b/docs.json @@ -538,6 +538,7 @@ "ui-kit/react/components/sticker-bubble", "ui-kit/react/components/collaborative-document-bubble", "ui-kit/react/components/collaborative-whiteboard-bubble", + "ui-kit/react/components/card-bubble", "ui-kit/react/components/call-bubble", "ui-kit/react/components/call-action-bubble", "ui-kit/react/components/group-action-bubble", diff --git a/ui-kit/react/components-overview.mdx b/ui-kit/react/components-overview.mdx index 92b300942..344bead0b 100644 --- a/ui-kit/react/components-overview.mdx +++ b/ui-kit/react/components-overview.mdx @@ -145,6 +145,7 @@ Message bubble components accept a `message` object and self-extract all require | `CometChatStickerBubble` | `extension_sticker` | Sticker image display | [Sticker Bubble](/ui-kit/react/components/sticker-bubble) | | `CometChatCollaborativeDocumentBubble` | `extension_document` | Document collaboration link with join button | [Collaborative Document Bubble](/ui-kit/react/components/collaborative-document-bubble) | | `CometChatCollaborativeWhiteboardBubble` | `extension_whiteboard` | Whiteboard collaboration link with join button | [Collaborative Whiteboard Bubble](/ui-kit/react/components/collaborative-whiteboard-bubble) | +| `CometChatCardBubble` | `card` (category) | Developer-defined card messages drawn by the `CometChatCardView` renderer | [Card Bubble](/ui-kit/react/components/card-bubble) | | `CometChatGroupActionBubble` | `groupMember` | Group membership system messages (joined, left, kicked, banned, scope change) | [Group Action Bubble](/ui-kit/react/components/group-action-bubble) | | `CometChatCallActionBubble` | `audio`, `video` (call category) | Call status system messages (missed, outgoing, incoming, ended) | [Call Action Bubble](/ui-kit/react/components/call-action-bubble) | | `CometChatCallBubble` | `meeting` (custom) | Direct call / meeting invitation bubble | [Call Bubble](/ui-kit/react/components/call-bubble) | diff --git a/ui-kit/react/components/card-bubble.mdx b/ui-kit/react/components/card-bubble.mdx new file mode 100644 index 000000000..dc52fc66f --- /dev/null +++ b/ui-kit/react/components/card-bubble.mdx @@ -0,0 +1,191 @@ +--- +title: "Card Bubble" +sidebarTitle: "Card Bubble" +description: "A render-only bubble that draws developer-defined card messages (category \"card\") with the prebuilt CometChatCardView renderer and forwards card actions to your app." +--- + + +```json +{ + "component": "CometChatCardBubble", + "package": "@cometchat/chat-uikit-react", + "import": "import { CometChatCardBubble } from \"@cometchat/chat-uikit-react\";", + "description": "Render-only bubble for developer card messages (category \"card\"). Stringifies the raw payload from message.getCard() and hands it to the prebuilt CometChatCardView renderer, then forwards user actions back to the app. It never parses, mutates, or acts on the card itself.", + "cssRootClass": ".cometchat-card-bubble", + "renderOnly": true, + "props": { + "data": { + "message": { "type": "CometChat.CardMessage", "required": true, "note": "The developer card message (category \"card\"). Drives message.getCard()." }, + "themeMode": { "type": "CometChatCardThemeMode", "default": "\"auto\"", "note": "Theme mode forwarded to CometChatCardView." }, + "themeOverride": { "type": "CometChatCardThemeOverride", "note": "Optional theme overrides forwarded to the renderer." }, + "onCardAction": { "type": "(message: CometChat.BaseMessage, action: CometChatCardAction) => void", "note": "Direct callback for card actions, fired in addition to the ui:card/action event." } + } + } +} +``` + + +## Overview + +`CometChatCardBubble` renders a **card message** — a message with `category: "card"`. A card message carries a block of Card Schema JSON that is created and sent server-side (via the Platform (REST) API or the Dashboard Bubble Builder) and delivered to clients like any other message. Card messages are **receive-only**: the UI Kit renders them, it does not send them. + +The bubble is **render-only**, mirroring `CometChatTextBubble`: the kit performs zero transformation. It stringifies the raw payload from `message.getCard()` and hands it to the prebuilt [`CometChatCardView`](https://www.npmjs.com/package/@cometchat/cards-react) renderer (`@cometchat/cards-react`), then forwards user actions back to your app. It never parses or mutates the card body, and never performs an action itself — your app owns all action behavior (opening URLs, navigating to chats, API calls, etc.). + +In the message list, card messages are routed to this bubble automatically by the built-in **Card plugin** — no configuration is required. See [Plugins → Built-in Plugins](/ui-kit/react/plugins/overview#built-in-plugins). + +### Where cards fit in the message hierarchy + +`card` is a top-level message category, alongside `message`, `custom`, `action`, and `call`. + + + + + +--- + +## Usage + +Card messages render automatically inside `CometChatMessageList`. To render one directly — for example in a custom layout — pass the SDK `CardMessage` to the bubble: + +```tsx +import { CometChat } from "@cometchat/chat-sdk-javascript"; +import { CometChatCardBubble } from "@cometchat/chat-uikit-react"; + +function CardMessageItem({ message }: { message: CometChat.CardMessage }) { + return ; +} +``` + +To receive card actions without going through the [event bus](/ui-kit/react/event-system), pass an `onCardAction` callback: + +```tsx +import { CometChat } from "@cometchat/chat-sdk-javascript"; +import { + CometChatCardBubble, + type CometChatCardAction, +} from "@cometchat/chat-uikit-react"; + +function CardMessageItem({ message }: { message: CometChat.CardMessage }) { + const handleAction = ( + msg: CometChat.BaseMessage, + action: CometChatCardAction + ) => { + // Your app owns the behavior — open a URL, start a call, call an API, etc. + console.log("Card action", action, "on message", msg.getId()); + }; + + return ; +} +``` + +--- + +## Props + +### message + +The developer card message (`category: "card"`). The bubble reads the raw card payload from `message.getCard()`. **Required.** + +| | | +| --- | --- | +| Type | `CometChat.CardMessage` | +| Required | Yes | + +--- + +### themeMode + +Theme mode forwarded to the `CometChatCardView` renderer. + +| | | +| --- | --- | +| Type | `CometChatCardThemeMode` | +| Default | `"auto"` | + +--- + +### themeOverride + +Optional theme overrides forwarded to the renderer. + +| | | +| --- | --- | +| Type | `CometChatCardThemeOverride` | +| Default | `undefined` | + +--- + +### onCardAction + +Direct callback for card actions. Fired **in addition to** the `ui:card/action` UI event, so an app embedding the bubble directly can receive actions without subscribing to the event bus. Receives the message and the clicked action. + +| | | +| --- | --- | +| Type | `(message: CometChat.BaseMessage, action: CometChatCardAction) => void` | +| Default | `undefined` | + +--- + +## Card Actions + +When a user clicks an action inside a card (a button, link, etc.), the bubble forwards the raw action to your app through **two** channels — it never handles the action itself: + +1. The optional [`onCardAction`](#oncardaction) prop, when provided. +2. The [`ui:card/action`](/ui-kit/react/event-system#card-actions) UI event, published on the event bus with the `message` and the clicked `action`. This is the only channel that can reach a card rendered by the kit (e.g. a nested agent card) where no prop is reachable. + +Subscribe to the event anywhere in your app: + +```tsx +import { useCometChatEvents } from "@cometchat/chat-uikit-react"; + +function CardActionListener() { + useCometChatEvents((event) => { + if (event.type === "ui:card/action") { + // event.message, event.action + console.log("Card action clicked:", event.action); + } + }); + + return null; +} +``` + +--- + +## Fallback + +When `message.getCard()` is absent or empty, the renderer is **not** invoked. Instead the bubble renders a plain-text fallback, resolving the first available of: + +1. `message.getFallbackText()` +2. `message.getText()` +3. The localized `"Card Message"` string + +--- + +## CSS Selectors + +| Target | Selector | +| --- | --- | +| Root | `.cometchat-card-bubble` | +| Text fallback | `.cometchat-card-bubble__fallback` | + +The card body itself is styled by the `CometChatCardView` renderer; use `themeMode` / `themeOverride` to theme it. + +--- + +## Next Steps + + + + How the Card plugin routes card messages to this bubble + + + Subscribe to the ui:card/action event + + + The wrapper that hosts bubble content + + + Customize colors, fonts, and spacing + + diff --git a/ui-kit/react/event-system.mdx b/ui-kit/react/event-system.mdx index d47424d8e..a2b35e12e 100644 --- a/ui-kit/react/event-system.mdx +++ b/ui-kit/react/event-system.mdx @@ -11,7 +11,7 @@ description: "Unified pub/sub event system that merges SDK listener events with | Publish hook | `const publish = usePublishEvent()` | | Provider | `CometChatEventsProvider` (mounted automatically by `CometChatProvider` after login) | | Event prefix | SDK events: `message/`, `receipt/`, `user/`, `group/`, `call/`, `connection/` | -| UI event prefix | `ui:message/`, `ui:compose/`, `ui:group/`, `ui:call/`, `ui:thread/`, `ui:conversation/` | +| UI event prefix | `ui:message/`, `ui:compose/`, `ui:group/`, `ui:call/`, `ui:thread/`, `ui:conversation/`, `ui:card/` | @@ -114,6 +114,7 @@ These events originate from the CometChat SDK (network). They fire when other us | `message/media-received` | `{ message: MediaMessage }` | Media message received | | `message/custom-received` | `{ message: CustomMessage }` | Custom message received | | `message/interactive-received` | `{ message: InteractiveMessage }` | Interactive message received | +| `message/card-received` | `{ message: BaseMessage }` | Card message (`category: "card"`) received | | `message/edited` | `{ message: BaseMessage }` | Message was edited | | `message/deleted` | `{ message: BaseMessage }` | Message was deleted | | `message/moderated` | `{ message: BaseMessage }` | Message was moderated | @@ -247,6 +248,14 @@ These events are published by UI Kit components for local cross-component commun | --- | --- | --- | | `ui:open-chat` | `{ user?, group? }` | MessageList (message privately option) | +### Card Actions + +| Event Type | Payload | Published by | +| --- | --- | --- | +| `ui:card/action` | `{ message, action }` | [Card Bubble](/ui-kit/react/components/card-bubble) (user clicks a card action) | + +Published when a user clicks an action (button, link, etc.) inside a card message bubble. The kit performs no behavior — it forwards the raw `action` and its `message` to your app, so you own all action handling. This is the only channel that can reach a kit-instantiated card (e.g. a nested agent card) where no prop is reachable. + ### Panels | Event Type | Payload | Published by | diff --git a/ui-kit/react/plugins/overview.mdx b/ui-kit/react/plugins/overview.mdx index 0f5d50282..b9497302f 100644 --- a/ui-kit/react/plugins/overview.mdx +++ b/ui-kit/react/plugins/overview.mdx @@ -105,6 +105,7 @@ These plugins are included automatically — no configuration needed. Each route | **Stickers** | `extension_sticker` | `custom` | Sticker image extracted from the message metadata | [Sticker Bubble](/ui-kit/react/components/sticker-bubble) | | **Collaborative Document** | `extension_document` | `custom` | Document card with an "Open Document" button | [Collaborative Document Bubble](/ui-kit/react/components/collaborative-document-bubble) | | **Collaborative Whiteboard** | `extension_whiteboard` | `custom` | Whiteboard card with an "Open Whiteboard" button | [Collaborative Whiteboard Bubble](/ui-kit/react/components/collaborative-whiteboard-bubble) | +| **Card** | any | `card` | Developer-defined card messages, drawn by the `CometChatCardView` renderer | [Card Bubble](/ui-kit/react/components/card-bubble) | | **Group Action** | `groupMember` | `action` | Centered system messages (joined, left, kicked, banned, scope change) | [Group Action Bubble](/ui-kit/react/components/group-action-bubble) | | **Call Action** | `audio` / `video` | `call` | Centered call status messages (missed, outgoing, incoming, ended) | [Call Action Bubble](/ui-kit/react/components/call-action-bubble) | | **Meeting** | `meeting` | `custom` | Group/conference call invite card with a **Join** button | [Call Bubble](/ui-kit/react/components/call-bubble) |