From 12ff1c4c83bb852d7a2ef2264f5bda06ae119d98 Mon Sep 17 00:00:00 2001 From: PrajwalDhuleCC Date: Mon, 1 Jun 2026 16:13:01 +0530 Subject: [PATCH 01/11] docs(ui-kit/react): add documentation for react uikit v7 --- docs.json | 255 +++- ui-kit/react/ai-assistant.mdx | 286 ++++ ui-kit/react/ai-features-overview.mdx | 322 +++++ ui-kit/react/ai-features.mdx | 22 +- ui-kit/react/astro-conversation.mdx | 289 ++-- ui-kit/react/astro-one-to-one-chat.mdx | 266 ++-- ui-kit/react/astro-tab-based-chat.mdx | 677 +++------ ui-kit/react/call-features.mdx | 40 +- ui-kit/react/calling-integration.mdx | 250 +++- ui-kit/react/calling-overview.mdx | 216 +++ ui-kit/react/cometchat-provider.mdx | 317 ++++ ui-kit/react/components-overview.mdx | 285 ++-- ui-kit/react/components/action-sheet.mdx | 490 +++++++ ui-kit/react/components/ai-assistant-chat.mdx | 661 +++++++++ ui-kit/react/components/ai-assistant.mdx | 548 +++++++ ui-kit/react/components/avatar.mdx | 393 +++++ ui-kit/react/components/button.mdx | 317 ++++ ui-kit/react/components/call-buttons.mdx | 382 +++++ ui-kit/react/components/call-logs.mdx | 476 ++++++ ui-kit/react/components/change-scope.mdx | 612 ++++++++ ui-kit/react/components/checkbox.mdx | 318 ++++ .../collaborative-document-bubble.mdx | 172 +++ .../collaborative-whiteboard-bubble.mdx | 35 + .../components/cometchat-group-members.mdx | 383 +++++ ui-kit/react/components/cometchat-groups.mdx | 338 +++++ ui-kit/react/components/cometchat-users.mdx | 831 +++++++++++ ui-kit/react/components/confirm-dialog.mdx | 486 +++++++ ui-kit/react/components/context-menu.mdx | 567 ++++++++ .../react/components/conversation-starter.mdx | 548 +++++++ .../react/components/conversation-summary.mdx | 412 ++++++ ui-kit/react/components/conversations.mdx | 713 +++++++++ ui-kit/react/components/create-poll.mdx | 254 ++++ ui-kit/react/components/date.mdx | 394 +++++ ui-kit/react/components/dropdown.mdx | 335 +++++ ui-kit/react/components/emoji-keyboard.mdx | 600 ++++++++ ui-kit/react/components/error-boundary.mdx | 291 ++++ .../react/components/flag-message-dialog.mdx | 511 +++++++ ui-kit/react/components/fullscreen-viewer.mdx | 535 +++++++ ui-kit/react/components/group-members.mdx | 621 ++++++++ ui-kit/react/components/groups.mdx | 592 ++++++++ ui-kit/react/components/incoming-call.mdx | 438 ++++++ ui-kit/react/components/link-dialog.mdx | 307 ++++ ui-kit/react/components/link-popover.mdx | 275 ++++ ui-kit/react/components/list-item.mdx | 608 ++++++++ ui-kit/react/components/media-recorder.mdx | 282 ++++ ui-kit/react/components/message-bubble.mdx | 152 ++ ui-kit/react/components/message-composer.mdx | 1063 ++++++++++++++ ui-kit/react/components/message-header.mdx | 664 +++++++++ .../react/components/message-information.mdx | 177 +++ ui-kit/react/components/message-list.mdx | 1286 +++++++++++++++++ ui-kit/react/components/message-preview.mdx | 263 ++++ ui-kit/react/components/outgoing-call.mdx | 356 +++++ ui-kit/react/components/paginated-list.mdx | 645 +++++++++ ui-kit/react/components/poll-bubble.mdx | 161 +++ ui-kit/react/components/popover.mdx | 402 ++++++ ui-kit/react/components/radio-button.mdx | 374 +++++ ui-kit/react/components/reaction-list.mdx | 352 +++++ ui-kit/react/components/reactions.mdx | 302 ++++ ui-kit/react/components/search-bar.mdx | 546 +++++++ ui-kit/react/components/search.mdx | 727 ++++++++++ ui-kit/react/components/smart-replies.mdx | 466 ++++++ ui-kit/react/components/sticker-bubble.mdx | 101 ++ ui-kit/react/components/stickers-keyboard.mdx | 184 +++ ui-kit/react/components/text-bubble.mdx | 153 ++ ui-kit/react/components/thread-header.mdx | 528 +++++++ ui-kit/react/components/thread-view.mdx | 327 +++++ ui-kit/react/components/toast.mdx | 299 ++++ ui-kit/react/components/typing-indicator.mdx | 213 +++ ui-kit/react/components/users.mdx | 590 ++++++++ ui-kit/react/core-features.mdx | 76 +- ui-kit/react/event-system.mdx | 268 ++++ ui-kit/react/extensions.mdx | 36 +- ui-kit/react/guide-block-unblock-user.mdx | 433 +++--- ui-kit/react/guide-group-chat-setup.mdx | 368 +++++ ui-kit/react/guide-message-privately.mdx | 391 +++-- ui-kit/react/guide-new-chat-creation.mdx | 429 ++++++ ui-kit/react/guide-search-messages.mdx | 324 +++-- ui-kit/react/guide-threaded-messages.mdx | 316 ++-- ui-kit/react/integration-astro.mdx | 245 ++++ ui-kit/react/integration-nextjs.mdx | 237 +++ ui-kit/react/integration-react-router.mdx | 245 ++++ ui-kit/react/integration-react.mdx | 224 +++ ui-kit/react/localization.mdx | 144 ++ ui-kit/react/methods.mdx | 612 ++------ ui-kit/react/migration-overview.mdx | 258 ++++ ui-kit/react/migration-property-changes.mdx | 532 +++++++ ui-kit/react/next-conversation.mdx | 374 ++--- ui-kit/react/next-one-to-one-chat.mdx | 267 ++-- ui-kit/react/next-tab-based-chat.mdx | 701 +++------ ui-kit/react/overview.mdx | 154 +- ui-kit/react/plugins/ai.mdx | 117 ++ ui-kit/react/plugins/audio.mdx | 61 + ui-kit/react/plugins/call-action.mdx | 79 + .../react/plugins/collaborative-document.mdx | 61 + .../plugins/collaborative-whiteboard.mdx | 61 + ui-kit/react/plugins/custom-plugin.mdx | 218 +++ ui-kit/react/plugins/delete.mdx | 60 + ui-kit/react/plugins/file.mdx | 61 + ui-kit/react/plugins/group-action.mdx | 66 + ui-kit/react/plugins/image.mdx | 68 + ui-kit/react/plugins/message-translation.mdx | 88 ++ ui-kit/react/plugins/overview.mdx | 251 ++++ ui-kit/react/plugins/polls.mdx | 68 + ui-kit/react/plugins/stickers.mdx | 58 + ui-kit/react/plugins/text-formatters.mdx | 214 +++ ui-kit/react/plugins/text.mdx | 88 ++ ui-kit/react/plugins/video.mdx | 59 + ui-kit/react/quick-start.mdx | 169 +++ ui-kit/react/react-conversation.mdx | 381 +---- ui-kit/react/react-one-to-one-chat.mdx | 191 +-- ui-kit/react/react-router-conversation.mdx | 404 ++---- ui-kit/react/react-router-one-to-one-chat.mdx | 288 ++-- ui-kit/react/react-router-tab-based-chat.mdx | 720 +++------ ui-kit/react/react-tab-based-chat.mdx | 653 +++------ ui-kit/react/sound-manager.mdx | 123 +- ui-kit/react/theme/color-resources.mdx | 275 ++-- ui-kit/react/theme/message-bubble-styling.mdx | 1122 ++------------ ui-kit/react/theming.mdx | 264 ++++ ui-kit/react/troubleshooting.mdx | 305 ++-- ui-kit/react/{ => v6}/ai-assistant-chat.mdx | 0 ui-kit/react/v6/ai-features.mdx | 69 + ui-kit/react/v6/astro-conversation.mdx | 270 ++++ ui-kit/react/{ => v6}/astro-integration.mdx | 0 ui-kit/react/v6/astro-one-to-one-chat.mdx | 262 ++++ ui-kit/react/v6/astro-tab-based-chat.mdx | 536 +++++++ ui-kit/react/{ => v6}/call-buttons.mdx | 0 ui-kit/react/v6/call-features.mdx | 82 ++ ui-kit/react/{ => v6}/call-logs.mdx | 0 ui-kit/react/v6/calling-integration.mdx | 28 + ui-kit/react/{ => v6}/campaigns.mdx | 0 .../{ => v6}/compact-message-composer.mdx | 0 ui-kit/react/v6/components-overview.mdx | 167 +++ ui-kit/react/{ => v6}/conversations.mdx | 0 ui-kit/react/v6/core-features.mdx | 244 ++++ .../{ => v6}/custom-text-formatter-guide.mdx | 0 ui-kit/react/{ => v6}/events.mdx | 0 ui-kit/react/v6/extensions.mdx | 197 +++ ui-kit/react/{ => v6}/group-members.mdx | 0 ui-kit/react/{ => v6}/groups.mdx | 0 ui-kit/react/v6/guide-block-unblock-user.mdx | 212 +++ .../react/{ => v6}/guide-call-log-details.mdx | 0 ui-kit/react/{ => v6}/guide-group-chat.mdx | 0 ui-kit/react/v6/guide-message-privately.mdx | 189 +++ ui-kit/react/{ => v6}/guide-new-chat.mdx | 0 ui-kit/react/{ => v6}/guide-overview.mdx | 0 ui-kit/react/v6/guide-search-messages.mdx | 132 ++ ui-kit/react/v6/guide-threaded-messages.mdx | 189 +++ ui-kit/react/{ => v6}/incoming-call.mdx | 0 ui-kit/react/{ => v6}/link/changelog.mdx | 0 ui-kit/react/{ => v6}/link/figma.mdx | 0 ui-kit/react/{ => v6}/link/sample.mdx | 0 ui-kit/react/{ => v6}/localize.mdx | 0 .../{ => v6}/mentions-formatter-guide.mdx | 0 ui-kit/react/{ => v6}/message-composer.mdx | 0 ui-kit/react/{ => v6}/message-header.mdx | 0 ui-kit/react/{ => v6}/message-list.mdx | 0 ui-kit/react/{ => v6}/message-template.mdx | 0 ui-kit/react/v6/methods.mdx | 594 ++++++++ .../{ => v6}/moved/builder-customisations.mdx | 0 .../{ => v6}/moved/builder-dir-structure.mdx | 0 .../moved/builder-integration-nextjs.mdx | 0 .../builder-integration-react-router.mdx | 0 .../{ => v6}/moved/builder-integration.mdx | 0 .../react/{ => v6}/moved/builder-settings.mdx | 0 ui-kit/react/v6/next-conversation.mdx | 388 +++++ ui-kit/react/{ => v6}/next-js-integration.mdx | 0 ui-kit/react/v6/next-one-to-one-chat.mdx | 263 ++++ ui-kit/react/v6/next-tab-based-chat.mdx | 608 ++++++++ ui-kit/react/{ => v6}/notification-feed.mdx | 0 ui-kit/react/{ => v6}/outgoing-call.mdx | 0 ui-kit/react/v6/overview.mdx | 171 +++ ui-kit/react/v6/react-conversation.mdx | 406 ++++++ .../react/{ => v6}/react-js-integration.mdx | 0 ui-kit/react/v6/react-one-to-one-chat.mdx | 201 +++ ui-kit/react/v6/react-router-conversation.mdx | 411 ++++++ .../{ => v6}/react-router-integration.mdx | 0 .../react/v6/react-router-one-to-one-chat.mdx | 280 ++++ .../react/v6/react-router-tab-based-chat.mdx | 623 ++++++++ ui-kit/react/v6/react-tab-based-chat.mdx | 557 +++++++ ui-kit/react/{ => v6}/search.mdx | 0 .../{ => v6}/shortcut-formatter-guide.mdx | 0 ui-kit/react/v6/sound-manager.mdx | 101 ++ ui-kit/react/{ => v6}/theme.mdx | 0 ui-kit/react/v6/theme/color-resources.mdx | 215 +++ .../react/v6/theme/message-bubble-styling.mdx | 1100 ++++++++++++++ ui-kit/react/{ => v6}/thread-header.mdx | 0 ui-kit/react/v6/troubleshooting.mdx | 125 ++ ui-kit/react/{ => v6}/upgrading-from-v5.mdx | 0 ui-kit/react/{ => v6}/url-formatter-guide.mdx | 0 ui-kit/react/{ => v6}/users.mdx | 0 190 files changed, 43689 insertions(+), 6419 deletions(-) create mode 100644 ui-kit/react/ai-assistant.mdx create mode 100644 ui-kit/react/ai-features-overview.mdx create mode 100644 ui-kit/react/calling-overview.mdx create mode 100644 ui-kit/react/cometchat-provider.mdx create mode 100644 ui-kit/react/components/action-sheet.mdx create mode 100644 ui-kit/react/components/ai-assistant-chat.mdx create mode 100644 ui-kit/react/components/ai-assistant.mdx create mode 100644 ui-kit/react/components/avatar.mdx create mode 100644 ui-kit/react/components/button.mdx create mode 100644 ui-kit/react/components/call-buttons.mdx create mode 100644 ui-kit/react/components/call-logs.mdx create mode 100644 ui-kit/react/components/change-scope.mdx create mode 100644 ui-kit/react/components/checkbox.mdx create mode 100644 ui-kit/react/components/collaborative-document-bubble.mdx create mode 100644 ui-kit/react/components/collaborative-whiteboard-bubble.mdx create mode 100644 ui-kit/react/components/cometchat-group-members.mdx create mode 100644 ui-kit/react/components/cometchat-groups.mdx create mode 100644 ui-kit/react/components/cometchat-users.mdx create mode 100644 ui-kit/react/components/confirm-dialog.mdx create mode 100644 ui-kit/react/components/context-menu.mdx create mode 100644 ui-kit/react/components/conversation-starter.mdx create mode 100644 ui-kit/react/components/conversation-summary.mdx create mode 100644 ui-kit/react/components/conversations.mdx create mode 100644 ui-kit/react/components/create-poll.mdx create mode 100644 ui-kit/react/components/date.mdx create mode 100644 ui-kit/react/components/dropdown.mdx create mode 100644 ui-kit/react/components/emoji-keyboard.mdx create mode 100644 ui-kit/react/components/error-boundary.mdx create mode 100644 ui-kit/react/components/flag-message-dialog.mdx create mode 100644 ui-kit/react/components/fullscreen-viewer.mdx create mode 100644 ui-kit/react/components/group-members.mdx create mode 100644 ui-kit/react/components/groups.mdx create mode 100644 ui-kit/react/components/incoming-call.mdx create mode 100644 ui-kit/react/components/link-dialog.mdx create mode 100644 ui-kit/react/components/link-popover.mdx create mode 100644 ui-kit/react/components/list-item.mdx create mode 100644 ui-kit/react/components/media-recorder.mdx create mode 100644 ui-kit/react/components/message-bubble.mdx create mode 100644 ui-kit/react/components/message-composer.mdx create mode 100644 ui-kit/react/components/message-header.mdx create mode 100644 ui-kit/react/components/message-information.mdx create mode 100644 ui-kit/react/components/message-list.mdx create mode 100644 ui-kit/react/components/message-preview.mdx create mode 100644 ui-kit/react/components/outgoing-call.mdx create mode 100644 ui-kit/react/components/paginated-list.mdx create mode 100644 ui-kit/react/components/poll-bubble.mdx create mode 100644 ui-kit/react/components/popover.mdx create mode 100644 ui-kit/react/components/radio-button.mdx create mode 100644 ui-kit/react/components/reaction-list.mdx create mode 100644 ui-kit/react/components/reactions.mdx create mode 100644 ui-kit/react/components/search-bar.mdx create mode 100644 ui-kit/react/components/search.mdx create mode 100644 ui-kit/react/components/smart-replies.mdx create mode 100644 ui-kit/react/components/sticker-bubble.mdx create mode 100644 ui-kit/react/components/stickers-keyboard.mdx create mode 100644 ui-kit/react/components/text-bubble.mdx create mode 100644 ui-kit/react/components/thread-header.mdx create mode 100644 ui-kit/react/components/thread-view.mdx create mode 100644 ui-kit/react/components/toast.mdx create mode 100644 ui-kit/react/components/typing-indicator.mdx create mode 100644 ui-kit/react/components/users.mdx create mode 100644 ui-kit/react/event-system.mdx create mode 100644 ui-kit/react/guide-group-chat-setup.mdx create mode 100644 ui-kit/react/guide-new-chat-creation.mdx create mode 100644 ui-kit/react/integration-astro.mdx create mode 100644 ui-kit/react/integration-nextjs.mdx create mode 100644 ui-kit/react/integration-react-router.mdx create mode 100644 ui-kit/react/integration-react.mdx create mode 100644 ui-kit/react/localization.mdx create mode 100644 ui-kit/react/migration-overview.mdx create mode 100644 ui-kit/react/migration-property-changes.mdx create mode 100644 ui-kit/react/plugins/ai.mdx create mode 100644 ui-kit/react/plugins/audio.mdx create mode 100644 ui-kit/react/plugins/call-action.mdx create mode 100644 ui-kit/react/plugins/collaborative-document.mdx create mode 100644 ui-kit/react/plugins/collaborative-whiteboard.mdx create mode 100644 ui-kit/react/plugins/custom-plugin.mdx create mode 100644 ui-kit/react/plugins/delete.mdx create mode 100644 ui-kit/react/plugins/file.mdx create mode 100644 ui-kit/react/plugins/group-action.mdx create mode 100644 ui-kit/react/plugins/image.mdx create mode 100644 ui-kit/react/plugins/message-translation.mdx create mode 100644 ui-kit/react/plugins/overview.mdx create mode 100644 ui-kit/react/plugins/polls.mdx create mode 100644 ui-kit/react/plugins/stickers.mdx create mode 100644 ui-kit/react/plugins/text-formatters.mdx create mode 100644 ui-kit/react/plugins/text.mdx create mode 100644 ui-kit/react/plugins/video.mdx create mode 100644 ui-kit/react/quick-start.mdx create mode 100644 ui-kit/react/theming.mdx rename ui-kit/react/{ => v6}/ai-assistant-chat.mdx (100%) create mode 100644 ui-kit/react/v6/ai-features.mdx create mode 100644 ui-kit/react/v6/astro-conversation.mdx rename ui-kit/react/{ => v6}/astro-integration.mdx (100%) create mode 100644 ui-kit/react/v6/astro-one-to-one-chat.mdx create mode 100644 ui-kit/react/v6/astro-tab-based-chat.mdx rename ui-kit/react/{ => v6}/call-buttons.mdx (100%) create mode 100644 ui-kit/react/v6/call-features.mdx rename ui-kit/react/{ => v6}/call-logs.mdx (100%) create mode 100644 ui-kit/react/v6/calling-integration.mdx rename ui-kit/react/{ => v6}/campaigns.mdx (100%) rename ui-kit/react/{ => v6}/compact-message-composer.mdx (100%) create mode 100644 ui-kit/react/v6/components-overview.mdx rename ui-kit/react/{ => v6}/conversations.mdx (100%) create mode 100644 ui-kit/react/v6/core-features.mdx rename ui-kit/react/{ => v6}/custom-text-formatter-guide.mdx (100%) rename ui-kit/react/{ => v6}/events.mdx (100%) create mode 100644 ui-kit/react/v6/extensions.mdx rename ui-kit/react/{ => v6}/group-members.mdx (100%) rename ui-kit/react/{ => v6}/groups.mdx (100%) create mode 100644 ui-kit/react/v6/guide-block-unblock-user.mdx rename ui-kit/react/{ => v6}/guide-call-log-details.mdx (100%) rename ui-kit/react/{ => v6}/guide-group-chat.mdx (100%) create mode 100644 ui-kit/react/v6/guide-message-privately.mdx rename ui-kit/react/{ => v6}/guide-new-chat.mdx (100%) rename ui-kit/react/{ => v6}/guide-overview.mdx (100%) create mode 100644 ui-kit/react/v6/guide-search-messages.mdx create mode 100644 ui-kit/react/v6/guide-threaded-messages.mdx rename ui-kit/react/{ => v6}/incoming-call.mdx (100%) rename ui-kit/react/{ => v6}/link/changelog.mdx (100%) rename ui-kit/react/{ => v6}/link/figma.mdx (100%) rename ui-kit/react/{ => v6}/link/sample.mdx (100%) rename ui-kit/react/{ => v6}/localize.mdx (100%) rename ui-kit/react/{ => v6}/mentions-formatter-guide.mdx (100%) rename ui-kit/react/{ => v6}/message-composer.mdx (100%) rename ui-kit/react/{ => v6}/message-header.mdx (100%) rename ui-kit/react/{ => v6}/message-list.mdx (100%) rename ui-kit/react/{ => v6}/message-template.mdx (100%) create mode 100644 ui-kit/react/v6/methods.mdx rename ui-kit/react/{ => v6}/moved/builder-customisations.mdx (100%) rename ui-kit/react/{ => v6}/moved/builder-dir-structure.mdx (100%) rename ui-kit/react/{ => v6}/moved/builder-integration-nextjs.mdx (100%) rename ui-kit/react/{ => v6}/moved/builder-integration-react-router.mdx (100%) rename ui-kit/react/{ => v6}/moved/builder-integration.mdx (100%) rename ui-kit/react/{ => v6}/moved/builder-settings.mdx (100%) create mode 100644 ui-kit/react/v6/next-conversation.mdx rename ui-kit/react/{ => v6}/next-js-integration.mdx (100%) create mode 100644 ui-kit/react/v6/next-one-to-one-chat.mdx create mode 100644 ui-kit/react/v6/next-tab-based-chat.mdx rename ui-kit/react/{ => v6}/notification-feed.mdx (100%) rename ui-kit/react/{ => v6}/outgoing-call.mdx (100%) create mode 100644 ui-kit/react/v6/overview.mdx create mode 100644 ui-kit/react/v6/react-conversation.mdx rename ui-kit/react/{ => v6}/react-js-integration.mdx (100%) create mode 100644 ui-kit/react/v6/react-one-to-one-chat.mdx create mode 100644 ui-kit/react/v6/react-router-conversation.mdx rename ui-kit/react/{ => v6}/react-router-integration.mdx (100%) create mode 100644 ui-kit/react/v6/react-router-one-to-one-chat.mdx create mode 100644 ui-kit/react/v6/react-router-tab-based-chat.mdx create mode 100644 ui-kit/react/v6/react-tab-based-chat.mdx rename ui-kit/react/{ => v6}/search.mdx (100%) rename ui-kit/react/{ => v6}/shortcut-formatter-guide.mdx (100%) create mode 100644 ui-kit/react/v6/sound-manager.mdx rename ui-kit/react/{ => v6}/theme.mdx (100%) create mode 100644 ui-kit/react/v6/theme/color-resources.mdx create mode 100644 ui-kit/react/v6/theme/message-bubble-styling.mdx rename ui-kit/react/{ => v6}/thread-header.mdx (100%) create mode 100644 ui-kit/react/v6/troubleshooting.mdx rename ui-kit/react/{ => v6}/upgrading-from-v5.mdx (100%) rename ui-kit/react/{ => v6}/url-formatter-guide.mdx (100%) rename ui-kit/react/{ => v6}/users.mdx (100%) diff --git a/docs.json b/docs.json index 33faee4bc..200b8664e 100644 --- a/docs.json +++ b/docs.json @@ -451,7 +451,143 @@ "versions": [ { "version": "v6", - "default": true, + "default": true, + "groups": [ + { + "group": " ", + "pages": [ + "ui-kit/react/v6/overview", + { + "group": "Getting Started", + "pages": [ + { + "group": "React.js", + "pages": [ + "ui-kit/react/v6/react-js-integration", + "ui-kit/react/v6/react-conversation", + "ui-kit/react/v6/react-one-to-one-chat", + "ui-kit/react/v6/react-tab-based-chat" + ] + }, + { + "group": "Next.js", + "pages": [ + "ui-kit/react/v6/next-js-integration", + "ui-kit/react/v6/next-conversation", + "ui-kit/react/v6/next-one-to-one-chat", + "ui-kit/react/v6/next-tab-based-chat" + ] + }, + { + "group": "React-Router", + "pages": [ + "ui-kit/react/v6/react-router-integration", + "ui-kit/react/v6/react-router-conversation", + "ui-kit/react/v6/react-router-one-to-one-chat", + "ui-kit/react/v6/react-router-tab-based-chat" + ] + }, + { + "group": "Astro", + "pages": [ + "ui-kit/react/v6/astro-integration", + "ui-kit/react/v6/astro-conversation", + "ui-kit/react/v6/astro-one-to-one-chat", + "ui-kit/react/v6/astro-tab-based-chat" + ] + }, + "ui-kit/react/v6/calling-integration" + ] + }, + { + "group": "Features", + "pages": [ + { + "group": "Chat", + "pages": [ + "ui-kit/react/v6/core-features", + "ui-kit/react/v6/extensions", + "ui-kit/react/v6/ai-features" + ] + }, + "ui-kit/react/v6/call-features", + "ui-kit/react/v6/campaigns" + ] + }, + { + "group": "Theming", + "pages": [ + "ui-kit/react/v6/theme", + "ui-kit/react/v6/theme/color-resources", + "ui-kit/react/v6/theme/message-bubble-styling", + "ui-kit/react/v6/localize", + "ui-kit/react/v6/sound-manager" + ] + }, + { + "group": "Components", + "pages": [ + "ui-kit/react/v6/components-overview", + "ui-kit/react/v6/conversations", + "ui-kit/react/v6/users", + "ui-kit/react/v6/groups", + "ui-kit/react/v6/group-members", + "ui-kit/react/v6/message-header", + "ui-kit/react/v6/message-list", + "ui-kit/react/v6/message-composer", + "ui-kit/react/v6/compact-message-composer", + "ui-kit/react/v6/message-template", + "ui-kit/react/v6/thread-header", + "ui-kit/react/v6/incoming-call", + "ui-kit/react/v6/outgoing-call", + "ui-kit/react/v6/call-buttons", + "ui-kit/react/v6/call-logs", + "ui-kit/react/v6/search", + "ui-kit/react/v6/ai-assistant-chat", + "ui-kit/react/v6/notification-feed" + ] + }, + { + "group": "Reference", + "pages": [ + "ui-kit/react/v6/methods", + "ui-kit/react/v6/events" + ] + }, + { + "group": "Guides", + "pages": [ + "ui-kit/react/v6/guide-overview", + "ui-kit/react/v6/guide-threaded-messages", + "ui-kit/react/v6/guide-block-unblock-user", + "ui-kit/react/v6/guide-new-chat", + "ui-kit/react/v6/guide-message-privately", + "ui-kit/react/v6/guide-search-messages", + "ui-kit/react/v6/guide-call-log-details", + "ui-kit/react/v6/guide-group-chat", + "ui-kit/react/v6/custom-text-formatter-guide", + "ui-kit/react/v6/mentions-formatter-guide", + "ui-kit/react/v6/url-formatter-guide", + "ui-kit/react/v6/shortcut-formatter-guide" + ] + }, + { + "group": "Migration Guide", + "pages": [ + "ui-kit/react/v6/upgrading-from-v5" + ] + }, + "ui-kit/react/v6/troubleshooting", + "ui-kit/react/v6/link/sample", + "ui-kit/react/v6/link/changelog", + "ui-kit/react/v6/link/figma" + ] + } + ] + }, + { + "version": "v7", + "default": false, "groups": [ { "group": " ", @@ -463,7 +599,7 @@ { "group": "React.js", "pages": [ - "ui-kit/react/react-js-integration", + "ui-kit/react/integration-react", "ui-kit/react/react-conversation", "ui-kit/react/react-one-to-one-chat", "ui-kit/react/react-tab-based-chat" @@ -472,16 +608,16 @@ { "group": "Next.js", "pages": [ - "ui-kit/react/next-js-integration", + "ui-kit/react/integration-nextjs", "ui-kit/react/next-conversation", "ui-kit/react/next-one-to-one-chat", "ui-kit/react/next-tab-based-chat" ] }, { - "group": "React-Router", + "group": "React Router", "pages": [ - "ui-kit/react/react-router-integration", + "ui-kit/react/integration-react-router", "ui-kit/react/react-router-conversation", "ui-kit/react/react-router-one-to-one-chat", "ui-kit/react/react-router-tab-based-chat" @@ -490,7 +626,7 @@ { "group": "Astro", "pages": [ - "ui-kit/react/astro-integration", + "ui-kit/react/integration-astro", "ui-kit/react/astro-conversation", "ui-kit/react/astro-one-to-one-chat", "ui-kit/react/astro-tab-based-chat" @@ -510,77 +646,92 @@ "ui-kit/react/ai-features" ] }, - "ui-kit/react/call-features", - "ui-kit/react/campaigns" + "ui-kit/react/call-features" ] }, { - "group": "Theming", + "group": "Components", "pages": [ - "ui-kit/react/theme", + "ui-kit/react/components-overview", + "ui-kit/react/components/conversations", + "ui-kit/react/components/users", + "ui-kit/react/components/groups", + "ui-kit/react/components/group-members", + "ui-kit/react/components/message-header", + "ui-kit/react/components/message-list", + "ui-kit/react/components/message-composer", + "ui-kit/react/components/thread-header", + "ui-kit/react/components/incoming-call", + "ui-kit/react/components/outgoing-call", + "ui-kit/react/components/call-logs", + "ui-kit/react/components/search", + "ui-kit/react/components/ai-assistant-chat" + ] + }, + { + "group": "Architecture", + "pages": [ + "ui-kit/react/cometchat-provider", + "ui-kit/react/event-system" + ] + }, + { + "group": "Customization", + "pages": [ + "ui-kit/react/theming", "ui-kit/react/theme/color-resources", "ui-kit/react/theme/message-bubble-styling", - "ui-kit/react/localize", + "ui-kit/react/localization", "ui-kit/react/sound-manager" ] }, { - "group": "Components", + "group": "Plugins", "pages": [ - "ui-kit/react/components-overview", - "ui-kit/react/conversations", - "ui-kit/react/users", - "ui-kit/react/groups", - "ui-kit/react/group-members", - "ui-kit/react/message-header", - "ui-kit/react/message-list", - "ui-kit/react/message-composer", - "ui-kit/react/compact-message-composer", - "ui-kit/react/message-template", - "ui-kit/react/thread-header", - "ui-kit/react/incoming-call", - "ui-kit/react/outgoing-call", - "ui-kit/react/call-buttons", - "ui-kit/react/call-logs", - "ui-kit/react/search", - "ui-kit/react/ai-assistant-chat", - "ui-kit/react/notification-feed" + "ui-kit/react/plugins/overview", + "ui-kit/react/plugins/text", + "ui-kit/react/plugins/image", + "ui-kit/react/plugins/video", + "ui-kit/react/plugins/file", + "ui-kit/react/plugins/audio", + "ui-kit/react/plugins/stickers", + "ui-kit/react/plugins/polls", + "ui-kit/react/plugins/collaborative-document", + "ui-kit/react/plugins/collaborative-whiteboard", + "ui-kit/react/plugins/ai", + "ui-kit/react/plugins/message-translation", + "ui-kit/react/plugins/group-action", + "ui-kit/react/plugins/call-action", + "ui-kit/react/plugins/delete", + "ui-kit/react/plugins/custom-plugin", + "ui-kit/react/plugins/text-formatters" ] }, { - "group": "Reference", + "group": "How-To Guides", "pages": [ - "ui-kit/react/methods", - "ui-kit/react/events" + "ui-kit/react/guide-block-unblock-user", + "ui-kit/react/guide-group-chat-setup", + "ui-kit/react/guide-threaded-messages", + "ui-kit/react/guide-search-messages", + "ui-kit/react/guide-new-chat-creation", + "ui-kit/react/guide-message-privately" ] }, { - "group": "Guides", + "group": "Reference", "pages": [ - "ui-kit/react/guide-overview", - "ui-kit/react/guide-threaded-messages", - "ui-kit/react/guide-block-unblock-user", - "ui-kit/react/guide-new-chat", - "ui-kit/react/guide-message-privately", - "ui-kit/react/guide-search-messages", - "ui-kit/react/guide-call-log-details", - "ui-kit/react/guide-group-chat", - "ui-kit/react/custom-text-formatter-guide", - "ui-kit/react/mentions-formatter-guide", - "ui-kit/react/url-formatter-guide", - "ui-kit/react/shortcut-formatter-guide" + "ui-kit/react/methods" ] }, { "group": "Migration Guide", "pages": [ - "ui-kit/react/upgrading-from-v5" + "ui-kit/react/migration-overview", + "ui-kit/react/migration-property-changes", + "ui-kit/react/troubleshooting" ] - }, - "ui-kit/react/troubleshooting", - "ui-kit/react/link/sample", - "ui-kit/react/link/changelog", - "ui-kit/react/link/figma" + } ] } ] diff --git a/ui-kit/react/ai-assistant.mdx b/ui-kit/react/ai-assistant.mdx new file mode 100644 index 000000000..51a5531a5 --- /dev/null +++ b/ui-kit/react/ai-assistant.mdx @@ -0,0 +1,286 @@ +--- +title: "AI Assistant" +description: "Build a full AI chat experience with CometChatAIAssistantChat and render completed AI responses with CometChatAIAssistantBubble." +sidebarTitle: "AI Assistant" +--- + +## Overview + +The AI Assistant feature provides two components that work together to deliver AI-powered conversations: + +- **CometChatAIAssistantChat** — A full-screen AI chat orchestrator with message list, composer, chat history sidebar, and streaming support +- **CometChatAIAssistantBubble** — A bubble component that renders completed AI responses with markdown formatting and copy-to-clipboard + +Both components are part of the AI plugin system and integrate with the `CometChatAIPlugin` registered via `CometChatProvider`. + +## CometChatAIAssistantChat + +A complete AI chat interface that wraps `CometChatMessageList`, `CometChatMessageComposer`, and `CometChatMessageHeader` into a cohesive experience for conversing with an AI assistant. + +### Basic Usage + +```tsx +import { CometChat } from '@cometchat/chat-sdk-javascript'; +import { CometChatAIAssistantChat } from '@cometchat/chat-uikit-react/plugins/ai'; + +function AIChat() { + const [aiUser, setAiUser] = useState(null); + + useEffect(() => { + CometChat.getUser("ai-agent-uid").then(setAiUser); + }, []); + + if (!aiUser) return null; + + return ( + + ); +} +``` + +### Props + +| Prop | Type | Default | Description | +|---|---|---|---| +| `user` | `CometChat.User` | — | **Required.** The AI assistant user object. | +| `streamingSpeed` | `number` | `30` | Delay in milliseconds between text chunks during streaming. | +| `aiAssistantTools` | `CometChatAIAssistantTools` | — | Client-side tool handlers for function calls. | +| `loadLastAgentConversation` | `boolean` | `false` | Auto-load the most recent conversation on mount. | +| `showSuggestedMessages` | `boolean` | `true` | Whether to display suggestion pills in the greeting state. | +| `suggestedMessages` | `string[]` | `[]` | Custom suggestion texts. Overrides user metadata suggestions. | +| `greetingView` | `ReactNode` | — | Custom greeting view replacing the default greeting + intro. | +| `hideChatHistory` | `boolean` | `false` | Hide the chat history sidebar toggle button. | +| `hideNewChat` | `boolean` | `false` | Hide the "New Chat" button in the header. | +| `showBackButton` | `boolean` | `false` | Show a back button in the header. | +| `showCloseButton` | `boolean` | `false` | Show a close button in the header. | +| `onBackButtonClicked` | `() => void` | — | Callback when the back button is clicked. | +| `onCloseButtonClicked` | `() => void` | — | Callback when the close button is clicked. | +| `onSendButtonClick` | `(message: CometChat.BaseMessage) => void` | — | Callback when a message is sent. | +| `emptyView` | `ReactNode` | — | Custom empty state replacing the default greeting screen. | +| `loadingView` | `ReactNode` | — | Custom loading view. | +| `errorView` | `ReactNode` | — | Custom error view. | +| `onError` | `(error: unknown) => void` | — | Callback when an error occurs. | +| `className` | `string` | — | Custom CSS class name for the root element. | +| `parentMessageId` | `number` | — | Load a specific conversation thread by message ID. | + +### Chat History Sidebar + +The AI assistant includes a slide-in sidebar that displays past conversations with the AI agent. Users can browse previous threads and resume any conversation. + +```tsx + +``` + +**Sidebar behavior:** + +- Toggle the sidebar via the history icon button in the header +- Clicking a past conversation loads that thread in the message list +- The "New Chat" button (inside the sidebar) starts a fresh conversation +- An overlay dims the main chat area while the sidebar is open +- Focus is trapped within the sidebar when open and restored to the trigger button on close + +### Suggested Messages via User Metadata + +The greeting screen displays suggestion pills that users can tap to quickly start a conversation. Suggestions are configured through the AI assistant user's metadata: + +```typescript +// Set on the AI user's metadata (via CometChat Dashboard or SDK) +const metadata = { + greetingMessage: "Hi! I'm your AI assistant", + introductoryMessage: "I can help you with questions about our product.", + suggestedMessages: [ + "How do I get started?", + "What features are available?", + "Show me an example" + ] +}; +``` + +You can also override metadata suggestions with the `suggestedMessages` prop: + +```tsx + +``` + +When a suggestion pill is clicked, its text is inserted into the composer input via the `ui:compose/text` event. + +### Composer Behavior During Streaming + +While the AI is generating a response, the composer enters a disabled state: + +- The input area blocks keyboard interaction (prevents sending messages mid-stream) +- The send button displays a "streaming" visual state and is non-interactive +- Once the stream completes (`isComplete: true`), the composer re-enables automatically + +```tsx + +``` + +The `streamingSpeed` prop controls the delay between text chunks — lower values produce faster typing, higher values give a more readable streaming effect. + +### Full Example with Tools + +```tsx +import { + CometChatAIAssistantChat, + CometChatAIAssistantTools, +} from '@cometchat/chat-uikit-react/plugins/ai'; + +const tools = new CometChatAIAssistantTools({ + openProfile: (args) => { + const { userId } = args as { userId: string }; + navigate(`/users/${userId}`); + }, + showHelp: () => { + setHelpVisible(true); + }, +}); + +function AIPanel() { + return ( + setShowAI(false)} + onError={(err) => console.error('AI error:', err)} + /> + ); +} +``` + +## CometChatAIAssistantBubble + +Renders a completed AI assistant message with full markdown formatting and a copy-to-clipboard action. This component is used by the `CometChatAIPlugin`'s `renderBubble` method to display messages of type `assistant` in the `agentic` category. + +### Basic Usage + +```tsx +import { CometChatAIAssistantBubble } from '@cometchat/chat-uikit-react/plugins/ai'; + + +``` + +### Props + +| Prop | Type | Default | Description | +|---|---|---|---| +| `message` | `CometChat.BaseMessage` | — | **Required.** The AI assistant message to render. | +| `alignment` | `'left' \| 'right'` | `'left'` | Bubble alignment. `left` for incoming AI responses, `right` for outgoing. | +| `className` | `string` | — | Custom CSS class name. | + +### Markdown Rendering + +The bubble uses `CometChatMarkdownFormatter` to render rich content including: + +- **Bold**, *italic*, ~~strikethrough~~, and `inline code` +- Fenced code blocks with syntax highlighting +- Ordered and unordered lists +- Tables, blockquotes, and links +- Images (clickable to expand) + +All rendered HTML is sanitized via `sanitizeAIHtml()` before being injected into the DOM, preventing XSS from AI-generated content. + +### Copy-to-Clipboard + +A copy button is rendered below the message content. When clicked: + +1. The raw text (pre-markdown, without HTML) is copied to the clipboard +2. A "Copied!" confirmation appears briefly (2 seconds) +3. The `navigator.clipboard` API is used with a `document.execCommand` fallback for older browsers + +### Alignment + +The `alignment` prop controls the bubble's visual positioning: + +- `'left'` (default) — AI responses appear on the left side of the message list, styled as incoming messages +- `'right'` — Used when the AI message is contextually sent by the current user (rare) + +The alignment value is set via a `data-alignment` attribute on the root element, which CSS uses for directional styling (border radius, background color). + +### AIPlugin renderBubble Relationship + +You typically don't render `CometChatAIAssistantBubble` directly. The `CometChatAIPlugin` handles rendering automatically when it encounters an `assistant` type message: + +```typescript +// Inside CometChatAIPlugin.renderBubble(): +// For messages with type === 'assistant' and category === 'agentic' +renderBubble(message, context) { + const alignment = context.alignment === 'right' ? 'right' : 'left'; + const type = message.getType(); + + if (type === 'assistant') { + return ( + + + + ); + } + // ... other message types (toolArguments, toolResults, run_started) +} +``` + +The bubble component is lazy-loaded — it's only fetched when the first AI assistant message needs to render, keeping it out of the initial bundle. + +### Plugin Registration + +To enable AI assistant bubbles in the message list, register the `CometChatAIPlugin`: + +```tsx +import { CometChatProvider } from '@cometchat/chat-uikit-react'; +import { defaultPlugins } from '@cometchat/chat-uikit-react/plugins/core'; +import { CometChatAIPlugin } from '@cometchat/chat-uikit-react/plugins/ai'; + + + {/* AI assistant messages will render with CometChatAIAssistantBubble */} + +``` + +## Streaming State Reference + +Both components interact with the streaming service. Here's the state shape that drives rendering: + +```typescript +interface CometChatStreamState { + text: string; // Accumulated text content + isComplete: boolean; // Whether the stream has finished + activeToolCall: string | null; + toolExecutionText: string; + isThinking: boolean; // AI processing before first text + hasContent: boolean; // Whether any text has been received + hasError: boolean; // Network/offline error occurred + hasStarted: boolean; // Whether streaming has begun +} +``` + +| State | Composer Behavior | Bubble Behavior | +|---|---|---| +| `hasStarted && !isComplete` | Input disabled, send button shows streaming icon | `CometChatStreamMessageBubble` renders with typing effect | +| `isComplete` | Input re-enabled, send button active | `CometChatAIAssistantBubble` renders final markdown | +| `hasError` | Input re-enabled | Error indicator shown | + +## Related Pages + +- [AI Features Overview](/ui-kit/react/ai-features-overview) — AIPlugin registration, streaming service architecture, event flow +- [Plugin System](/ui-kit/react/plugin-system) — How plugins work, PluginRegistry, renderBubble lifecycle +- [CometChatProvider](/ui-kit/react/cometchat-provider) — Root provider setup and plugin registration diff --git a/ui-kit/react/ai-features-overview.mdx b/ui-kit/react/ai-features-overview.mdx new file mode 100644 index 000000000..f1bb33452 --- /dev/null +++ b/ui-kit/react/ai-features-overview.mdx @@ -0,0 +1,322 @@ +--- +title: "AI Features Overview" +description: "Register the AIPlugin, handle AI message types, and integrate streaming AI responses in your chat application." +--- + +## Overview + +The AI features in CometChat React UI Kit v7 are delivered as an **extension plugin** — opt-in, lazy-loaded, and registered through the same plugin system that powers all message rendering. The `CometChatAIPlugin` handles AI assistant messages, tool call visualization, and real-time streaming responses. + +The AI plugin integrates with CometChat's server-side AI Assistant feature. When enabled on your CometChat dashboard, the SDK delivers AI-generated messages through a dedicated `agentic` message category, and streams partial responses via WebSocket events that the plugin renders in real time. + +**Key capabilities:** + +- Render completed AI assistant messages with markdown formatting +- Display live streaming responses with a typing effect +- Visualize tool call arguments and results +- Conversation list previews for AI messages +- Configurable streaming speed +- Client-side tool execution via `CometChatAIAssistantTools` + +## Interface / API + +The AI plugin implements the standard `CometChatMessagePlugin` interface: + +```typescript +import type { CometChatMessagePlugin } from '@cometchat/chat-uikit-react'; + +const CometChatAIPlugin: CometChatMessagePlugin = { + id: 'ai', + + messageTypes: ['assistant', 'toolArguments', 'toolResults', 'run_started'], + + messageCategories: ['agentic', 'custom'], + + renderBubble(message, context) { /* ... */ }, + getOptions(message, context) { /* returns [] — AI messages have no context menu */ }, + getLastMessagePreview(message) { /* returns plain-text preview */ }, + getAttachmentOption(context) { /* returns null — AI chat uses a dedicated button */ }, +}; +``` + +### Message Types Handled + +| Message Type | Category | Bubble Component | Description | +|---|---|---|---| +| `assistant` | `agentic` | `CometChatAIAssistantBubble` | Completed AI response with markdown | +| `toolArguments` | `agentic` | `CometChatToolCallArgumentBubble` | Tool call arguments (JSON) | +| `toolResults` | `agentic` | `CometChatToolCallResultBubble` | Tool call results (JSON) | +| `run_started` | `custom` | `CometChatStreamMessageBubble` | Live streaming placeholder | + +### Conversation List Previews + +The plugin provides `getLastMessagePreview()` for the conversation list subtitle: + +| Message Type | Preview Format | +|---|---| +| `assistant` | `🤖 {first 80 chars of plain text}` | +| `toolArguments` | `🔧 Tool call` | +| `toolResults` | `✅ Tool result` | + +## Streaming Service Architecture + +The streaming service (`CometChatAIStreamingService`) is a module-level singleton that manages real-time AI response delivery. It processes SDK WebSocket events and exposes reactive state that bubble components subscribe to. + +### How It Works + +``` +SDK WebSocket Events + │ + ▼ +┌─────────────────────────┐ +│ handleWebsocketMessage │ ← Pushes events into the queue +│ (per chatId) │ +└───────────┬─────────────┘ + │ + ▼ +┌─────────────────────────┐ +│ Sequential Queue │ ← Processes events one at a time +│ (no drops) │ with configurable delay for typing effect +└───────────┬─────────────┘ + │ + ▼ +┌─────────────────────────┐ +│ Per-chatId State Map │ ← StreamState per conversation +│ (text, isComplete, │ +│ activeToolCall, etc.) │ +└───────────┬─────────────┘ + │ + ▼ +┌─────────────────────────┐ +│ Subscriber Listeners │ ← Bubble components re-render on state change +└─────────────────────────┘ +``` + +### Stream State + +Each active stream is tracked per `chatId` with the following state shape: + +```typescript +interface CometChatStreamState { + text: string; // Accumulated text content + isComplete: boolean; // Whether the stream has finished + activeToolCall: string | null; // Currently executing tool name + toolExecutionText: string; // Description of tool being executed + isThinking: boolean; // AI is processing (before first text) + hasContent: boolean; // Whether any text has been received + hasError: boolean; // Network/offline error occurred + hasStarted: boolean; // Whether streaming has begun +} +``` + +### Stream Event Flow + +The SDK delivers these events in sequence during an AI response: + +1. `run_started` — AI begins processing +2. `text_message_start` — First text chunk incoming +3. `text_message_content` (repeated) — Text delta chunks +4. `text_message_end` — Text generation complete +5. `tool_call_start` — Tool invocation begins (optional) +6. `tool_call_args` (repeated) — Tool argument deltas (optional) +7. `tool_call_end` — Tool execution complete (optional) +8. `run_finished` — Entire response complete + +### Streaming Service API + +```typescript +import { + handleWebsocketMessage, + startStreamingMessage, + stopStreamingMessage, + setStreamSpeed, + getStreamState, + subscribeToStreamState, + setStreamError, + isStreaming, + setAIAssistantTools, +} from '@cometchat/chat-uikit-react/plugins/ai'; + +// Configure typing speed (ms between text chunks) +setStreamSpeed(30); + +// Subscribe to stream state changes for a conversation +const unsubscribe = subscribeToStreamState(chatId, () => { + const state = getStreamState(chatId); + console.log('Stream update:', state.text, state.isComplete); +}); + +// Check if streaming is active +const active = isStreaming(chatId); + +// Clean up +unsubscribe(); +``` + +## Integration with CometChatProvider + +### Step 1: Register AIPlugin + +Add `CometChatAIPlugin` to the `plugins` array alongside `defaultPlugins`: + +```tsx +import { CometChatProvider } from '@cometchat/chat-uikit-react'; +import { defaultPlugins } from '@cometchat/chat-uikit-react/plugins/core'; +import { CometChatAIPlugin } from '@cometchat/chat-uikit-react/plugins/ai'; + +function App() { + return ( + + {/* Your chat UI */} + + ); +} +``` + +### Step 2: Enable AI Assistant on CometChat Dashboard + +Before AI messages can be received, you must enable the AI Assistant feature in your [CometChat Dashboard](https://app.cometchat.com): + +1. Navigate to **AI** → **AI Agents** in your dashboard +2. Create or configure an AI agent +3. Note the agent's UID — this is the `user` you pass to `CometChatAIAssistantChat` + +### Step 3: Set Up SDK AI Assistant Listener + +The CometChat SDK provides an AI Assistant listener that delivers streaming events. The `CometChatAIAssistantChat` component handles this internally, but if you need manual control: + +```typescript +import { CometChat } from '@cometchat/chat-sdk-javascript'; +import { handleWebsocketMessage } from '@cometchat/chat-uikit-react/plugins/ai'; + +const listenerId = 'ai-stream-listener'; + +CometChat.addAIAssistantListener( + listenerId, + new CometChat.AIAssistantListener({ + onAssistantEvent(event: CometChat.AIAssistantBaseEvent) { + const chatId = event.getReceiverId(); + handleWebsocketMessage(event, chatId); + }, + }) +); + +// Clean up when done +CometChat.removeAIAssistantListener(listenerId); +``` + + +In most cases, you don't need to set up the listener manually. The `CometChatAIAssistantChat` component manages listener registration and cleanup automatically. + + +## Built-in Components + +The AI plugin provides these bubble components: + +| Component | Purpose | Lazy-Loaded | +|---|---|---| +| `CometChatAIAssistantBubble` | Renders completed AI responses with markdown | Yes | +| `CometChatStreamMessageBubble` | Renders live streaming text with typing effect | No (inline) | +| `CometChatToolCallArgumentBubble` | Displays tool call arguments as formatted JSON | Yes | +| `CometChatToolCallResultBubble` | Displays tool call results as formatted JSON | Yes | +| `CometChatAIAssistantChat` | Full AI chat orchestrator (Tier 4 lazy) | Yes | +| `CometChatAIAssistantChatHistory` | Chat history sidebar | No | + +## Advanced Patterns + +### Configuring Streaming Speed + +Control the typing effect speed (delay between text chunks): + +```typescript +import { setStreamSpeed } from '@cometchat/chat-uikit-react/plugins/ai'; + +// Faster streaming (20ms between chunks) +setStreamSpeed(20); + +// Slower, more readable streaming (50ms between chunks) +setStreamSpeed(50); +``` + +Or pass it as a prop to `CometChatAIAssistantChat`: + +```tsx + +``` + +### Registering Client-Side Tool Handlers + +When the AI agent calls tools, you can handle them on the client: + +```tsx +import { + CometChatAIAssistantTools, + CometChatAIAssistantChat, +} from '@cometchat/chat-uikit-react/plugins/ai'; + +const tools = new CometChatAIAssistantTools({ + openUserProfile: (args) => { + const { userId } = args as { userId: string }; + navigate(`/users/${userId}`); + }, + showNotification: (args) => { + const { message } = args as { message: string }; + toast.info(message); + }, +}); + +; +``` + +### Using createCometChatAIPlugin Factory + +For configuration options, use the factory function: + +```tsx +import { createCometChatAIPlugin } from '@cometchat/chat-uikit-react/plugins/ai'; + +const aiPlugin = createCometChatAIPlugin({ + enableAssistantPanel: true, + enableSmartReplies: true, + enableConversationSummary: true, + enableConversationStarters: true, +}); + + +``` + +### Preloading the AI Assistant Chat + +Reduce perceived latency by preloading the AI chat component on hover: + +```tsx +import { preloadAIAssistantChat } from '@cometchat/chat-uikit-react/plugins/ai'; + + +``` + +### Error Handling During Streaming + +If a network error occurs during streaming, the service marks the stream with an error state: + +```typescript +import { setStreamError, getStreamState } from '@cometchat/chat-uikit-react/plugins/ai'; + +// The stream bubble will display an error indicator +// when state.hasError is true +const state = getStreamState(chatId); +if (state.hasError) { + // Show retry UI +} +``` diff --git a/ui-kit/react/ai-features.mdx b/ui-kit/react/ai-features.mdx index e929a26f5..a5cb18010 100644 --- a/ui-kit/react/ai-features.mdx +++ b/ui-kit/react/ai-features.mdx @@ -8,9 +8,9 @@ description: "AI-powered features in CometChat's React UI Kit: Conversation Star | Field | Value | | --- | --- | | Package | `@cometchat/chat-uikit-react` | -| Required setup | `CometChatUIKit.init(UIKitSettings)` then `CometChatUIKit.login("UID")` + AI features enabled in [CometChat Dashboard](/fundamentals/ai-user-copilot/overview) | +| Required setup | Wrap app in `CometChatProvider` with valid credentials + AI features enabled in [CometChat Dashboard](/fundamentals/ai-user-copilot/overview) | | AI features | Conversation Starter, Smart Replies, Conversation Summary | -| Key components | `CometChatMessageList` → [Message List](/ui-kit/react/message-list) (Conversation Starter), `CometChatMessageComposer` → [Message Composer](/ui-kit/react/message-composer) (Smart Replies, Summary), `CometChatAIAssistantChat` → [AI Assistant Chat](/ui-kit/react/ai-assistant-chat) | +| Key components | `CometChatMessageList` → [Message List](/components/message-list) (Conversation Starter), `CometChatMessageComposer` → [Message Composer](/components/message-composer) (Smart Replies, Summary), `CometChatAIAssistantChat` → [AI Assistant Chat](/components/ai-assistant-chat) | | Activation | Enable each AI feature from the CometChat Dashboard — UI Kit auto-integrates them, no additional code required | @@ -19,13 +19,17 @@ description: "AI-powered features in CometChat's React UI Kit: Conversation Star CometChat AI features enhance user interaction by providing contextual suggestions and summaries. Each feature is activated from the Dashboard and auto-integrates into UI Kit components. + +The [AI Assistant Chat](/components/ai-assistant-chat) component requires `CometChatAIPlugin` to be configured in your `CometChatProvider` plugins. See the [AI Assistant Chat](/components/ai-assistant-chat) component page for setup details. + + ## Smart Chat Features ### Conversation Starter Displays AI-generated opening lines when a user starts a new chat. See [Conversation Starter](/fundamentals/ai-user-copilot/conversation-starter). -Auto-integrates into [MessageList](/ui-kit/react/message-list) when activated. +Auto-integrates into [MessageList](/components/message-list) when activated. @@ -35,7 +39,7 @@ Auto-integrates into [MessageList](/ui-kit/react/message-list) when activated. AI-generated response suggestions based on conversation context. See [Smart Replies](/fundamentals/ai-user-copilot/smart-replies). -Auto-integrates into the Action Sheet of [MessageComposer](/ui-kit/react/message-composer) when activated. +Auto-integrates into the Action Sheet of [MessageComposer](/components/message-composer) when activated. @@ -45,7 +49,7 @@ Auto-integrates into the Action Sheet of [MessageComposer](/ui-kit/react/message AI-generated recap of long conversations. See [Conversation Summary](/fundamentals/ai-user-copilot/conversation-summary). -Auto-integrates into the Action Sheet of [MessageComposer](/ui-kit/react/message-composer) when activated. +Auto-integrates into the Action Sheet of [MessageComposer](/components/message-composer) when activated. @@ -54,16 +58,16 @@ Auto-integrates into the Action Sheet of [MessageComposer](/ui-kit/react/message ## Next Steps - + AI-powered assistant component - + Customize the message list where AI features appear - + Customize the composer with Smart Replies and Summary - + Core chat features like messaging and reactions diff --git a/ui-kit/react/astro-conversation.mdx b/ui-kit/react/astro-conversation.mdx index 975ac29b3..3e10e3a41 100644 --- a/ui-kit/react/astro-conversation.mdx +++ b/ui-kit/react/astro-conversation.mdx @@ -1,7 +1,7 @@ --- title: "Conversation List + Message View" sidebarTitle: "Conversation List + Message View" -description: "Build CometChat UI Kit conversation list and message view layouts in Astro with navigation, headers, lists, and composers." +description: "Build a two-panel conversation list + message view layout in Astro with CometChat UI Kit." --- @@ -9,22 +9,22 @@ description: "Build CometChat UI Kit conversation list and message view layouts | Field | Value | | --- | --- | | Package | `@cometchat/chat-uikit-react` | -| Framework | Astro (with `@astrojs/react` islands) | +| Framework | Astro | | Components | `CometChatConversations`, `CometChatMessageHeader`, `CometChatMessageList`, `CometChatMessageComposer` | | Layout | Two-panel — conversation list (left) + message view (right) | -| Prerequisite | Complete [Astro Integration](/ui-kit/react/astro-integration) Steps 1–5 first | -| SSR | `client:only="react"` directive — CometChat requires browser APIs | +| Prerequisite | Complete [Astro Integration](/integration-astro) first | +| SSR | React island with `client:only="react"` directive | | Pattern | WhatsApp Web, Slack, Microsoft Teams | -This guide builds a two-panel chat layout — conversation list on the left, messages on the right. Users tap a conversation to open it. +This guide builds a two-panel chat layout — conversation list on the left, messages on the right. Users click a conversation to open it. -This assumes you've already completed [Astro Integration](/ui-kit/react/astro-integration) (project created, React added, UI Kit installed). +This assumes you've already completed [Astro Integration](/integration-astro) (project created, UI Kit installed, init + login working). - - - +{/* TODO:IMAGE - Two-panel chat layout showing Conversations sidebar + MessageList/Composer */} + +{/* TODO:SANDBOX - Link to CodeSandbox for conversation list + messages */} --- @@ -38,233 +38,138 @@ Three sections working together: --- -## Step 1 — Create the React Island - -Create a `ChatApp` component inside `src/components/`. This is a React island that handles init, login, and renders the full chat experience. - - - - - - - - - +## Full Code - - +Create a React island component with the chat UI, then render it in an Astro page with `client:only="react"`. -```tsx title="ChatApp.tsx" lines highlight={15-17, 20} -import { useEffect, useState } from "react"; +```tsx title="src/components/ConversationChat.tsx" +import { useState } from "react"; +import { CometChat } from "@cometchat/chat-sdk-javascript"; import { + CometChatProvider, CometChatConversations, - CometChatMessageComposer, CometChatMessageHeader, CometChatMessageList, - CometChatUIKit, - UIKitSettingsBuilder, + CometChatMessageComposer, } from "@cometchat/chat-uikit-react"; -import { CometChat } from "@cometchat/chat-sdk-javascript"; -import "@cometchat/chat-uikit-react/css-variables.css"; -import "./ChatApp.css"; - -const COMETCHAT_CONSTANTS = { - APP_ID: "", // Replace with your App ID - REGION: "", // Replace with your Region - AUTH_KEY: "", // Replace with your Auth Key (dev only) -}; - -const UID = "cometchat-uid-1"; // Replace with your actual UID +import "@cometchat/chat-uikit-react/styles"; -export default function ChatApp() { - const [user, setUser] = useState(undefined); +export default function ConversationChat() { const [selectedUser, setSelectedUser] = useState(undefined); const [selectedGroup, setSelectedGroup] = useState(undefined); - useEffect(() => { - const UIKitSettings = new UIKitSettingsBuilder() - .setAppId(COMETCHAT_CONSTANTS.APP_ID) - .setRegion(COMETCHAT_CONSTANTS.REGION) - .setAuthKey(COMETCHAT_CONSTANTS.AUTH_KEY) - .subscribePresenceForAllUsers() - .build(); - - CometChatUIKit.init(UIKitSettings) - .then(() => { - console.log("Initialization completed successfully"); - CometChatUIKit.getLoggedinUser().then((loggedInUser) => { - if (!loggedInUser) { - CometChatUIKit.login(UID) - .then((u) => { - console.log("Login Successful", { u }); - setUser(u); - }) - .catch((error) => console.error("Login failed", error)); - } else { - console.log("Already logged-in", { loggedInUser }); - setUser(loggedInUser); - } - }); - }) - .catch((error) => console.error("Initialization failed", error)); - }, []); - - if (!user) return
Initializing Chat...
; + const handleConversationClick = (conversation: CometChat.Conversation) => { + const entity = conversation.getConversationWith(); + if (conversation.getConversationType() === "user") { + setSelectedUser(entity as CometChat.User); + setSelectedGroup(undefined); + } else { + setSelectedGroup(entity as CometChat.Group); + setSelectedUser(undefined); + } + }; return ( -
-
- { - let item: any = activeItem; - if (activeItem instanceof CometChat.Conversation) { - item = activeItem.getConversationWith(); - } - if (item instanceof CometChat.User) { - setSelectedUser(item); - setSelectedGroup(undefined); - } else if (item instanceof CometChat.Group) { - setSelectedUser(undefined); - setSelectedGroup(item); - } else { - setSelectedUser(undefined); - setSelectedGroup(undefined); - } - }} - /> -
- - {selectedUser || selectedGroup ? ( -
- - - + +
+
+
- ) : ( -
Select a conversation to start chatting
- )} -
- ); -} -``` - - - - -```css title="ChatApp.css" lines -.conversations-with-messages { - display: flex; - height: 100%; - width: 100%; -} - -.conversations-wrapper { - height: 100%; - width: 480px; - overflow: hidden; - display: flex; - flex-direction: column; -} -.conversations-wrapper > .cometchat { - overflow: hidden; -} - -.messages-wrapper { - width: calc(100% - 480px); - height: 100%; - display: flex; - flex-direction: column; -} - -.empty-conversation { - height: 100%; - width: 100%; - display: flex; - justify-content: center; - align-items: center; - background: var(--cometchat-background-color-03, #F5F5F5); - color: var(--cometchat-text-color-secondary, #727272); - font: var(--cometchat-font-body-regular, 400 14px Roboto); -} - -.cometchat .cometchat-message-composer { - border-radius: 0px; + {selectedUser || selectedGroup ? ( +
+ + + +
+ ) : ( +
+ Select a conversation to start chatting +
+ )} +
+ + ); } ``` - - - -**How it works**: -- Init and login happen inside `useEffect` — the component only renders chat UI after login resolves. -- When a conversation is tapped, the `User` or `Group` is extracted from the `Conversation` object. -- `selectedUser` / `selectedGroup` state drives which chat is displayed — pass either `user` or `group` to the message components, never both. - +```astro title="src/pages/chat.astro" --- - -## Step 2 — Render the Astro Page - -Import the island and hydrate it client-side using `client:only="react"`. - -```astro title="src/pages/index.astro" lines ---- -import ChatApp from "../components/ChatApp.tsx"; -import "../styles/globals.css"; +import ConversationChat from '../components/ConversationChat.tsx'; --- - CometChat + Astro + + Chat - - + + ``` -The `client:only="react"` directive ensures the component skips SSR entirely and only renders in the browser — required because CometChat needs `window` and `WebSocket`. +--- + +## How It Works + +1. **`client:only="react"`** tells Astro to skip server-rendering and hydrate the component entirely on the client. This is required because CometChat uses browser APIs. +2. **React island** — the CometChat UI lives in a self-contained React component. Astro handles the page shell, React handles the interactive chat. +3. **CometChatProvider** wraps the entire tree — it supplies theme, locale, and event context to all CometChat components. +4. **CometChatConversations** renders the sidebar list. When a user clicks a conversation, `onItemClick` fires with the `Conversation` object. +5. **handleConversationClick** extracts the `User` or `Group` from the conversation and stores it in state. +6. **Message components** (`MessageHeader`, `MessageList`, `MessageComposer`) receive either `user` or `group` as a prop — never both at the same time. --- -## Step 3 — Run the Project +## Run - - -```bash lines +```bash npm run dev ``` - - -```bash lines -pnpm dev -``` - - -```bash lines -yarn dev -``` - - -You should see the conversation list on the left. Tap any conversation to load messages on the right. +Open `http://localhost:4321/chat`. You should see the conversation list on the left. Click any conversation to load messages on the right. --- ## Next Steps - - Customize colors, fonts, and styles to match your brand + + Single chat window without a sidebar - - Browse all prebuilt UI components + + Tabbed navigation with Chats, Calls, Users - } href="/ui-kit/react/astro-integration"> - Back to the main setup guide + + Browse all prebuilt UI components - - Chat features included out of the box + + Customize colors, fonts, and styles diff --git a/ui-kit/react/astro-one-to-one-chat.mdx b/ui-kit/react/astro-one-to-one-chat.mdx index 99d45e160..70ddbe706 100644 --- a/ui-kit/react/astro-one-to-one-chat.mdx +++ b/ui-kit/react/astro-one-to-one-chat.mdx @@ -1,7 +1,7 @@ --- title: "One-to-One / Group Chat" sidebarTitle: "One-to-One / Group Chat" -description: "Build focused CometChat UI Kit chat screens in Astro with headers, message lists, composers, users, groups, and direct navigation." +description: "Build a single chat window for one-to-one or group messaging in Astro with CometChat UI Kit." --- @@ -9,22 +9,22 @@ description: "Build focused CometChat UI Kit chat screens in Astro with headers, | Field | Value | | --- | --- | | Package | `@cometchat/chat-uikit-react` | -| Framework | Astro (with `@astrojs/react` islands) | +| Framework | Astro | | Components | `CometChatMessageHeader`, `CometChatMessageList`, `CometChatMessageComposer` | | Layout | Single chat window — no sidebar, no conversation list | -| Prerequisite | Complete [Astro Integration](/ui-kit/react/astro-integration) Steps 1–5 first | -| SSR | `client:only="react"` directive — CometChat requires browser APIs | +| Prerequisite | Complete [Astro Integration](/integration-astro) first | +| SSR | React island with `client:only="react"` directive | | Pattern | Support chat, embedded widgets, focused messaging | This guide builds a single chat window — no sidebar, no conversation list. Users go directly into a one-to-one or group chat. Good for support chat, embedded widgets, or any focused messaging experience. -This assumes you've already completed [Astro Integration](/ui-kit/react/astro-integration) (project created, React added, UI Kit installed). +This assumes you've already completed [Astro Integration](/integration-astro) (project created, UI Kit installed, init + login working). - - - +{/* TODO:IMAGE - Single chat window showing MessageHeader + MessageList + MessageComposer */} + +{/* TODO:SANDBOX - Link to CodeSandbox for one-to-one chat */} --- @@ -38,225 +38,137 @@ Three components stacked vertically: --- -## Step 1 — Create the React Island - -Create a `OneToOneChat` component inside `src/components/`. This handles init, login, fetches the target user, and renders the chat UI. +## Full Code - - - - - - - - +Create a React island component with the chat UI, then render it in an Astro page with `client:only="react"`. - - - -```tsx title="OneToOneChat.tsx" lines highlight={14-16, 37, 55, 62} +```tsx title="src/components/DirectChat.tsx" import { useEffect, useState } from "react"; +import { CometChat } from "@cometchat/chat-sdk-javascript"; import { - CometChatMessageComposer, + CometChatProvider, CometChatMessageHeader, CometChatMessageList, - CometChatUIKit, - UIKitSettingsBuilder, + CometChatMessageComposer, } from "@cometchat/chat-uikit-react"; -import { CometChat } from "@cometchat/chat-sdk-javascript"; -import "@cometchat/chat-uikit-react/css-variables.css"; -import "./OneToOneChat.css"; +import "@cometchat/chat-uikit-react/styles"; -const COMETCHAT_CONSTANTS = { - APP_ID: "", // Replace with your App ID - REGION: "", // Replace with your Region - AUTH_KEY: "", // Replace with your Auth Key (dev only) -}; +const RECIPIENT_UID = "cometchat-uid-2"; // Replace with the UID you want to chat with -export default function OneToOneChat() { - const [user, setUser] = useState(undefined); - const [selectedUser, setSelectedUser] = useState(undefined); - const [selectedGroup, setSelectedGroup] = useState(undefined); +export default function DirectChat() { + const [chatUser, setChatUser] = useState(undefined); useEffect(() => { - const UIKitSettings = new UIKitSettingsBuilder() - .setAppId(COMETCHAT_CONSTANTS.APP_ID) - .setRegion(COMETCHAT_CONSTANTS.REGION) - .setAuthKey(COMETCHAT_CONSTANTS.AUTH_KEY) - .subscribePresenceForAllUsers() - .build(); - - CometChatUIKit.init(UIKitSettings) - .then(() => { - console.log("Initialization completed successfully"); - CometChatUIKit.getLoggedinUser().then((loggedInUser) => { - if (!loggedInUser) { - CometChatUIKit.login("cometchat-uid-2") - .then((u) => { - console.log("Login Successful", { u }); - setUser(u); - }) - .catch((error) => console.error("Login failed", error)); - } else { - console.log("Already logged-in", { loggedInUser }); - setUser(loggedInUser); - } - }); - }) - .catch((error) => console.error("Initialization failed", error)); + CometChat.getUser(RECIPIENT_UID).then( + (user) => setChatUser(user), + (error) => console.error("User fetch failed:", error) + ); }, []); - useEffect(() => { - if (user) { - // Fetch the user whose chat you want to load - const UID = "cometchat-uid-1"; - CometChat.getUser(UID).then( - (u) => setSelectedUser(u), - (error) => console.log("User fetching failed with error:", error) - ); - - // To load a group chat instead, uncomment below: - // const GUID = "GUID"; - // CometChat.getGroup(GUID).then( - // (group) => setSelectedGroup(group), - // (error) => console.log("Group fetching failed with error:", error) - // ); - } - }, [user]); - - if (!user) return
Initializing Chat...
; + if (!chatUser) return
Loading chat...
; return ( - <> - {selectedUser || selectedGroup ? ( -
- - - -
- ) : ( -
- Set a user or group UID in OneToOneChat.tsx to start chatting -
- )} - + +
+ + + +
+
); } ``` -
- - -```css title="OneToOneChat.css" lines -.messages-wrapper { - width: 100%; - height: 100%; - display: flex; - flex-direction: column; -} - -.empty-conversation { - height: 100%; - width: 100%; - display: flex; - justify-content: center; - align-items: center; - background: var(--cometchat-background-color-03, #F5F5F5); - color: var(--cometchat-text-color-secondary, #727272); - font: var(--cometchat-font-body-regular, 400 14px Roboto); -} +```astro title="src/pages/chat.astro" +--- +import DirectChat from '../components/DirectChat.tsx'; +--- -.cometchat .cometchat-message-composer { - border-radius: 0px; -} + + + + + Chat + + + + + ``` - -
- Key points: -- `CometChat.getUser(UID)` fetches the user object from the SDK — you need a real user object, not a manually constructed one. +- `client:only="react"` ensures the component only runs in the browser — no server-side rendering. +- `CometChat.getUser(UID)` fetches the full user object from the SDK — you need a real user object, not a manually constructed one. - Pass either `user` or `group` to the message components, never both. -- The highlighted lines show where to set your credentials and target UID. +- The `RECIPIENT_UID` should be a user that exists in your CometChat app. Use one of the pre-created test UIDs: `cometchat-uid-1` through `cometchat-uid-5`. --- -## Switching Between User and Group Chat +## Switching to Group Chat -To load a group chat instead of one-to-one, replace the `getUser` call with `getGroup`: +To load a group chat instead of one-to-one, fetch a `Group` object and pass it to the message components: -```tsx lines highlight={1} -const GUID = "GUID"; // Replace with your actual Group ID - -CometChat.getGroup(GUID) - .then((group) => setSelectedGroup(group)) - .catch((error) => console.error("Failed to fetch group:", error)); -``` +```tsx title="src/components/DirectChat.tsx" +import { useEffect, useState } from "react"; +import { CometChat } from "@cometchat/chat-sdk-javascript"; +import { + CometChatProvider, + CometChatMessageHeader, + CometChatMessageList, + CometChatMessageComposer, +} from "@cometchat/chat-uikit-react"; +import "@cometchat/chat-uikit-react/styles"; ---- +const GROUP_ID = "cometchat-guid-1"; // Replace with your Group ID -## Step 2 — Render the Astro Page +export default function DirectChat() { + const [chatGroup, setChatGroup] = useState(undefined); -Import the island and hydrate it client-side using `client:only="react"`. + useEffect(() => { + CometChat.getGroup(GROUP_ID).then( + (group) => setChatGroup(group), + (error) => console.error("Group fetch failed:", error) + ); + }, []); -```astro title="src/pages/index.astro" lines ---- -import OneToOneChat from "../components/OneToOneChat.tsx"; -import "../styles/globals.css"; ---- + if (!chatGroup) return
Loading chat...
; - - - - One-to-One Chat - - - - - + return ( + +
+ + + +
+
+ ); +} ``` -The `client:only="react"` directive ensures the component skips SSR entirely and only renders in the browser. +The only difference: use `CometChat.getGroup(GUID)` instead of `CometChat.getUser(UID)`, and pass `group` instead of `user`. --- -## Step 3 — Run the Project +## Run - - -```bash lines +```bash npm run dev ``` - - -```bash lines -pnpm dev -``` - - -```bash lines -yarn dev -``` - - -You should see the chat window load with the conversation for the UID you set. +Open `http://localhost:4321/chat`. You should see the chat window load with the conversation for the UID or GUID you set. --- ## Next Steps - - Customize colors, fonts, and styles to match your brand + + Two-panel layout with a sidebar - - Browse all prebuilt UI components - - } href="/ui-kit/react/astro-integration"> - Back to the main setup guide + + Tabbed navigation with Chats, Calls, Users - - Chat features included out of the box + + Browse all prebuilt UI components diff --git a/ui-kit/react/astro-tab-based-chat.mdx b/ui-kit/react/astro-tab-based-chat.mdx index d8912dd91..bea72f9d1 100644 --- a/ui-kit/react/astro-tab-based-chat.mdx +++ b/ui-kit/react/astro-tab-based-chat.mdx @@ -1,7 +1,7 @@ --- title: "Tab-Based Chat" sidebarTitle: "Tab-Based Chat" -description: "Build a tab-based messaging UI with chats, calls, users, and groups in Astro with CometChat React UI Kit." +description: "Build a tab-based chat interface with Chat, Call Logs, Users, and Settings tabs in Astro." --- @@ -9,22 +9,22 @@ description: "Build a tab-based messaging UI with chats, calls, users, and group | Field | Value | | --- | --- | | Package | `@cometchat/chat-uikit-react` | -| Framework | Astro (with `@astrojs/react` islands) | -| Components | `CometChatConversations`, `CometChatCallLogs`, `CometChatUsers`, `CometChatGroups`, `CometChatMessageHeader`, `CometChatMessageList`, `CometChatMessageComposer` | -| Layout | Tabbed sidebar (Chats, Calls, Users, Groups) + message view | -| Prerequisite | Complete [Astro Integration](/ui-kit/react/astro-integration) Steps 1–5 first | -| SSR | `client:only="react"` directive — CometChat requires browser APIs | +| Framework | Astro | +| Components | `CometChatConversations`, `CometChatCallLogs`, `CometChatUsers`, `CometChatMessageHeader`, `CometChatMessageList`, `CometChatMessageComposer` | +| Layout | Tabbed sidebar (Chat, Calls, Users) + message view | +| Prerequisite | Complete [Astro Integration](/integration-astro) first | +| SSR | React island with `client:only="react"` directive | | Pattern | Full-featured messaging app with multiple sections | -This guide builds a tabbed messaging UI — Chats, Calls, Users, and Groups tabs in the sidebar, with a message view on the right. Good for full-featured apps that need more than just conversations. +This guide builds a tabbed messaging UI — Chat, Calls, and Users tabs in the sidebar, with a message view on the right. Good for full-featured apps that need more than just conversations. -This assumes you've already completed [Astro Integration](/ui-kit/react/astro-integration) (project created, React added, UI Kit installed). +This assumes you've already completed [Astro Integration](/integration-astro) (project created, UI Kit installed, init + login working). - - - +{/* TODO:IMAGE - Tab-based layout showing tab bar + sidebar list + message view */} + +{/* TODO:SANDBOX - Link to CodeSandbox for tab-based chat */} --- @@ -32,505 +32,266 @@ This assumes you've already completed [Astro Integration](/ui-kit/react/astro-in Three sections working together: -1. **Tab bar** — switches between Chats, Calls, Users, and Groups +1. **Tab bar** — switches between Chat, Calls, and Users 2. **Sidebar** — renders the list for the active tab 3. **Message view** — header + messages + composer for the selected item - ---- - -## Step 1 — Create the Tab Component - - - - - - - - - - - - -Tab icons need to be placed in `public/assets/`. Download them from the [CometChat UI Kit assets folder on GitHub](https://github.com/cometchat/cometchat-uikit-react/tree/v6/sample-app/src/assets). - - - - - - - - - - - - - - - -```tsx title="CometChatTabs.tsx" lines -import { useState } from "react"; -import "./CometChatTabs.css"; - -const chatsIcon = "/assets/chats.svg"; -const callsIcon = "/assets/calls.svg"; -const usersIcon = "/assets/users.svg"; -const groupsIcon = "/assets/groups.svg"; - -export const CometChatTabs = (props: { - onTabClicked?: (tabItem: { name: string; icon?: string }) => void; - activeTab?: string; -}) => { - const { onTabClicked = () => {}, activeTab } = props; - const [hoverTab, setHoverTab] = useState(""); - - const tabItems = [ - { name: "CHATS", icon: chatsIcon }, - { name: "CALLS", icon: callsIcon }, - { name: "USERS", icon: usersIcon }, - { name: "GROUPS", icon: groupsIcon }, - ]; - - return ( -
- {tabItems.map((tabItem) => { - const isActive = - activeTab === tabItem.name.toLowerCase() || - hoverTab === tabItem.name.toLowerCase(); - - return ( -
onTabClicked(tabItem)} - > -
setHoverTab(tabItem.name.toLowerCase())} - onMouseLeave={() => setHoverTab("")} - /> -
setHoverTab(tabItem.name.toLowerCase())} - onMouseLeave={() => setHoverTab("")} - > - {tabItem.name} -
-
- ); - })} -
- ); -}; -``` - - - - -```css title="CometChatTabs.css" lines -.cometchat-tab-component { - display: flex; - width: 100%; - padding: 0px 8px; - align-items: flex-start; - gap: 8px; - border-top: 1px solid var(--cometchat-border-color-light, #F5F5F5); - border-right: 1px solid var(--cometchat-border-color-light, #F5F5F5); - background: var(--cometchat-background-color-01, #FFF); -} - -.cometchat-tab-component__tab { - display: flex; - padding: 12px 0px 10px 0px; - flex-direction: column; - justify-content: center; - align-items: center; - gap: 4px; - flex: 1 0 0; - min-height: 48px; -} - -.cometchat-tab-component__tab-icon { - display: flex; - width: 32px; - height: 32px; - justify-content: center; - align-items: center; - background: var(--cometchat-icon-color-secondary); - -webkit-mask-size: contain; - -webkit-mask-position: center; - -webkit-mask-repeat: no-repeat; - mask-size: contain; - mask-position: center; - mask-repeat: no-repeat; - cursor: pointer; -} - -.cometchat-tab-component__tab-text { - color: var(--cometchat-text-color-secondary, #727272); - text-align: center; - font: var(--cometchat-font-caption1-medium, 500 12px Roboto); - cursor: pointer; -} - -.cometchat-tab-component__tab-icon-active { - background: var(--cometchat-icon-color-highlight); -} - -.cometchat-tab-component__tab-text-active { - color: var(--cometchat-text-color-highlight); -} -``` - - - - - ---- - -## Step 2 — Create the Sidebar Component - -The sidebar renders the list for whichever tab is active, plus the tab bar at the bottom. - - - - - - - - - - - - - - - -```tsx title="CometChatSelector.tsx" lines -import { useEffect, useState } from "react"; -import { Call, Conversation, Group, User, CometChat } from "@cometchat/chat-sdk-javascript"; -import { CometChatCallLogs, CometChatConversations, CometChatGroups, CometChatUIKitLoginListener, CometChatUsers } from "@cometchat/chat-uikit-react"; -import { CometChatTabs } from "../CometChatTabs/CometChatTabs"; - -interface SelectorProps { - onSelectorItemClicked?: (input: User | Group | Conversation | Call, type: string) => void; -} - -export const CometChatSelector = (props: SelectorProps) => { - const { onSelectorItemClicked = () => {} } = props; - const [loggedInUser, setLoggedInUser] = useState(); - const [activeItem, setActiveItem] = useState(); - const [activeTab, setActiveTab] = useState("chats"); - - useEffect(() => { - const user = CometChatUIKitLoginListener.getLoggedInUser(); - setLoggedInUser(user); - }, []); - - return ( - <> - {loggedInUser && ( - <> - {activeTab === "chats" && ( - { setActiveItem(item); onSelectorItemClicked(item, "updateSelectedItem"); }} - /> - )} - {activeTab === "calls" && ( - { setActiveItem(item); onSelectorItemClicked(item, "updateSelectedItemCall"); }} - /> - )} - {activeTab === "users" && ( - { setActiveItem(item); onSelectorItemClicked(item, "updateSelectedItemUser"); }} - /> - )} - {activeTab === "groups" && ( - { setActiveItem(item); onSelectorItemClicked(item, "updateSelectedItemGroup"); }} - /> - )} - - )} - setActiveTab(item.name.toLowerCase())} /> - - ); -}; -``` - - - - -```css title="CometChatSelector.css" lines -.selector-wrapper .cometchat-conversations .cometchat-list__header-menu .cometchat-button__icon { - background: var(--cometchat-icon-color-primary); -} -.cometchat-conversations .cometchat-list__header-menu .cometchat-button__icon:hover { - background: var(--cometchat-icon-color-highlight); -} -.cometchat-list__header-search-bar { border-right: none; } -.cometchat .cometchat-menu-list__sub-menu-list-item { text-align: left; } -.cometchat .cometchat-conversations .cometchat-menu-list__sub-menu-list { - width: 212px; top: 40px !important; left: 172px !important; -} -#logged-in-user { border-bottom: 2px solid var(--cometchat-border-color-default, #E8E8E8); } -#logged-in-user .cometchat-menu-list__sub-menu-item-title, -#logged-in-user .cometchat-menu-list__sub-menu-list-item { cursor: default; } -.cometchat-menu-list__sub-menu-list-item-icon-log-out { background-color: var(--cometchat-error-color, #F44649); } -.cometchat-menu-list__sub-menu-item-title-log-out { color: var(--cometchat-error-color, #F44649); } -.chat-menu .cometchat .cometchat-menu-list__sub-menu-item-title { cursor: pointer; } -.chat-menu .cometchat .cometchat-menu-list__sub-menu { box-shadow: none; } -.chat-menu .cometchat .cometchat-menu-list__sub-menu-icon { - background-color: var(--cometchat-icon-color-primary, #141414); width: 24px; height: 24px; -} -``` - - - - -Key points: -- The `activeTab` state drives which list component renders — `CometChatConversations`, `CometChatCallLogs`, `CometChatUsers`, or `CometChatGroups`. -- Each list component passes its selection back to the parent via `onSelectorItemClicked`. -- `CometChatTabs` renders at the bottom of the sidebar. - - --- -## Step 3 — Create the TabbedChat Island - -This component handles init, login, and renders the full tabbed chat experience. It runs client-side only via `client:only="react"`. +## Full Code - - - - - - - - +Create a React island component with the tabbed UI, then render it in an Astro page with `client:only="react"`. - - - -```tsx title="TabbedChat.tsx" lines highlight={15-17, 20} -import { useEffect, useState } from "react"; +```tsx title="src/components/TabbedChat.tsx" +import { useState } from "react"; +import { CometChat } from "@cometchat/chat-sdk-javascript"; import { - CometChatMessageComposer, + CometChatProvider, + CometChatConversations, + CometChatUsers, + CometChatCallLogs, CometChatMessageHeader, CometChatMessageList, - CometChatUIKit, - UIKitSettingsBuilder, + CometChatMessageComposer, } from "@cometchat/chat-uikit-react"; -import { CometChat } from "@cometchat/chat-sdk-javascript"; -import { CometChatSelector } from "./CometChatSelector/CometChatSelector"; -import "@cometchat/chat-uikit-react/css-variables.css"; -import "./TabbedChat.css"; +import "@cometchat/chat-uikit-react/styles"; -const COMETCHAT_CONSTANTS = { - APP_ID: "", // Replace with your App ID - REGION: "", // Replace with your Region - AUTH_KEY: "", // Replace with your Auth Key (dev only) -}; - -const UID = "cometchat-uid-4"; // Replace with your actual UID +type Tab = "chat" | "calls" | "users"; export default function TabbedChat() { - const [user, setUser] = useState(undefined); + const [activeTab, setActiveTab] = useState("chat"); const [selectedUser, setSelectedUser] = useState(undefined); const [selectedGroup, setSelectedGroup] = useState(undefined); - useEffect(() => { - const UIKitSettings = new UIKitSettingsBuilder() - .setAppId(COMETCHAT_CONSTANTS.APP_ID) - .setRegion(COMETCHAT_CONSTANTS.REGION) - .setAuthKey(COMETCHAT_CONSTANTS.AUTH_KEY) - .subscribePresenceForAllUsers() - .build(); - - CometChatUIKit.init(UIKitSettings) - .then(() => { - console.log("Initialization completed successfully"); - CometChatUIKit.getLoggedinUser().then((loggedInUser) => { - if (!loggedInUser) { - CometChatUIKit.login(UID) - .then((u) => { - console.log("Login Successful", { u }); - setUser(u); - }) - .catch((error) => console.error("Login failed", error)); - } else { - console.log("Already logged-in", { loggedInUser }); - setUser(loggedInUser); - } - }); - }) - .catch((error) => console.error("Initialization failed", error)); - }, []); - - if (!user) return
Initializing Chat...
; + const handleConversationClick = (conversation: CometChat.Conversation) => { + const entity = conversation.getConversationWith(); + if (conversation.getConversationType() === "user") { + setSelectedUser(entity as CometChat.User); + setSelectedGroup(undefined); + } else { + setSelectedGroup(entity as CometChat.Group); + setSelectedUser(undefined); + } + }; + + const handleUserClick = (user: CometChat.User) => { + setSelectedUser(user); + setSelectedGroup(undefined); + }; + + const handleCallClick = (call: any) => { + const initiator = call.getInitiator(); + const receiver = call.getReceiver(); + + // Determine the other party in the call + if (receiver instanceof CometChat.User) { + setSelectedUser(receiver); + setSelectedGroup(undefined); + } else if (receiver instanceof CometChat.Group) { + setSelectedUser(undefined); + setSelectedGroup(receiver); + } else if (initiator instanceof CometChat.User) { + setSelectedUser(initiator); + setSelectedGroup(undefined); + } + }; return ( -
-
- { - let item: any = activeItem; - if (activeItem instanceof CometChat.Conversation) { - item = activeItem.getConversationWith(); - } - if (item instanceof CometChat.User) { - setSelectedUser(item); - setSelectedGroup(undefined); - } else if (item instanceof CometChat.Group) { - setSelectedUser(undefined); - setSelectedGroup(item); - } else { - setSelectedUser(undefined); - setSelectedGroup(undefined); - } - }} - /> -
+ +
+
+
+ + + +
- {selectedUser || selectedGroup ? ( -
- - - +
+ {activeTab === "chat" && ( + + )} + {activeTab === "calls" && ( + + )} + {activeTab === "users" && ( + + )} +
- ) : ( -
Select a conversation to start chatting
- )} -
- ); -} -``` - - - -```css title="TabbedChat.css" lines -.conversations-with-messages { - display: flex; - height: 100%; - width: 100%; -} -.conversations-wrapper { - height: 100%; - width: 480px; - overflow: hidden; - display: flex; - flex-direction: column; -} -.conversations-wrapper > .cometchat { overflow: hidden; } -.messages-wrapper { - width: calc(100% - 480px); - height: 100%; - display: flex; - flex-direction: column; -} -.empty-conversation { - height: 100%; - width: 100%; - display: flex; - justify-content: center; - align-items: center; - background: var(--cometchat-background-color-03, #F5F5F5); - color: var(--cometchat-text-color-secondary, #727272); - font: var(--cometchat-font-body-regular, 400 14px Roboto); + {selectedUser || selectedGroup ? ( +
+ + + +
+ ) : ( +
+ Select a conversation to start chatting +
+ )} +
+
+ ); } -.cometchat .cometchat-message-composer { border-radius: 0px; } ``` - - - -How it works: -- Selections from any tab (Chats, Calls, Users, Groups) flow through the same `onSelectorItemClicked` callback. -- Conversation items are unwrapped via `getConversationWith()` to extract the underlying `User` or `Group`. -- Only one of `selectedUser` / `selectedGroup` is set at a time — the other is cleared. - +```astro title="src/pages/chat.astro" --- - -## Step 4 — Render the Astro Page - -Import the island and hydrate it client-side using `client:only="react"`. - -```astro title="src/pages/index.astro" lines ---- -import TabbedChat from "../components/TabbedChat.tsx"; -import "../styles/globals.css"; +import TabbedChat from '../components/TabbedChat.tsx'; --- - Tabbed Messaging UI + + Chat - + ``` -The `client:only="react"` directive ensures the component skips SSR entirely and only renders in the browser. +--- + +## How It Works + +1. **`client:only="react"`** tells Astro to skip server-rendering and hydrate the component entirely on the client. This is required because CometChat uses browser APIs. +2. **React island** — the CometChat UI lives in a self-contained React component. Astro handles the page shell, React handles the interactive chat. +3. **Tab state** — `activeTab` controls which list component renders in the sidebar. +4. **Conditional rendering** — only the active tab's component mounts. Switching tabs unmounts the previous list and mounts the new one. +5. **Unified selection** — all three tabs feed into the same `selectedUser` / `selectedGroup` state. Clicking any item (conversation, call log, or user) updates the message panel. +6. **Call log handling** — when a call log is clicked, the receiver (user or group) is extracted and passed to the message components. + +--- + +## Adding More Tabs + +To add a Groups tab, import `CometChatGroups` and add another tab button + conditional render: + +```tsx +import { CometChatGroups } from "@cometchat/chat-uikit-react"; + +// Add to Tab type: +type Tab = "chat" | "calls" | "users" | "groups"; + +// Add button in the tab bar: + + +// Add in the sidebar list: +{activeTab === "groups" && ( + { + setSelectedGroup(group); + setSelectedUser(undefined); + }} + /> +)} +``` + +You can follow the same pattern for any additional tabs (Settings, Contacts, etc.). --- -## Step 5 — Run the Project +## Run - - -```bash lines +```bash npm run dev ``` - - -```bash lines -pnpm dev -``` - - -```bash lines -yarn dev -``` - - -You should see the tab bar at the bottom of the sidebar. Switch between Chats, Calls, Users, and Groups — tapping any item loads the message view on the right. +Open `http://localhost:4321/chat`. You should see the tab bar at the top of the sidebar. Switch between Chats, Calls, and Users — clicking any item loads the message view on the right. --- ## Next Steps - - Customize colors, fonts, and styles to match your brand + + Two-panel layout without tabs - + Browse all prebuilt UI components - } href="/ui-kit/react/astro-integration"> - Back to the main setup guide - - - Chat features included out of the box + + Customize colors, fonts, and styles diff --git a/ui-kit/react/call-features.mdx b/ui-kit/react/call-features.mdx index 885bd6fa5..44f4375ee 100644 --- a/ui-kit/react/call-features.mdx +++ b/ui-kit/react/call-features.mdx @@ -8,31 +8,39 @@ description: "Overview of CometChat React UI Kit calling features, including inc | Field | Value | | --- | --- | | Packages | `@cometchat/chat-uikit-react` + `@cometchat/calls-sdk-javascript` (`npm install @cometchat/calls-sdk-javascript`) | -| Required setup | `CometChatUIKit.init(UIKitSettings)` then `CometChatUIKit.login("UID")` — Calls SDK must also be installed | -| Call features | Incoming Call, Outgoing Call, Call Logs, Call Buttons | -| Key components | `CometChatCallButtons` → [Call Buttons](/ui-kit/react/call-buttons), `CometChatIncomingCall` → [Incoming Call](/ui-kit/react/incoming-call), `CometChatOutgoingCall` → [Outgoing Call](/ui-kit/react/outgoing-call), `CometChatCallLogs` → [Call Logs](/ui-kit/react/call-logs) | -| Auto-detection | UI Kit automatically detects the Calls SDK and enables call UI components | +| Required setup | Wrap app in `CometChatProvider` with `callingEnabled={true}` — Calls SDK must also be installed | +| Call features | Incoming Call, Outgoing Call, Call Logs, Call Buttons (in Message Header) | +| Key components | `CometChatMessageHeader` → [Message Header](/components/message-header) (includes call buttons), `CometChatIncomingCall` → [Incoming Call](/components/incoming-call), `CometChatOutgoingCall` → [Outgoing Call](/components/outgoing-call), `CometChatCallLogs` → [Call Logs](/components/call-logs) | +| Enabling | Set `callingEnabled={true}` on `CometChatProvider` to activate call UI components | | CSS class prefix | `.cometchat-` | ## Overview -CometChat Calls integrates 1:1 and group audio/video calling into the React UI Kit. Install the Calls SDK and the UI Kit auto-detects it, enabling call components. +CometChat Calls integrates 1:1 and group audio/video calling into the React UI Kit. Install the Calls SDK and enable calling via the `callingEnabled` prop on `CometChatProvider` to activate call components. -Ensure `CometChatUIKit.init(UIKitSettings)` has completed and the user is logged in via `CometChatUIKit.login("UID")`. See [React.js Integration](/ui-kit/react/react-js-integration). +Ensure your app is wrapped in `CometChatProvider` with valid credentials and `callingEnabled={true}`. See [React.js Integration](/integration-react). ## Integration -Install the Calls SDK: +Install the Calls SDK and enable calling: ```bash lines npm install @cometchat/calls-sdk-javascript ``` -The React UI Kit auto-detects the SDK and activates calling features. [CallButtons](/ui-kit/react/call-buttons) renders in [MessageHeader](/ui-kit/react/message-header). +Then set `callingEnabled={true}` on your `CometChatProvider`: + +```jsx + + {/* your app */} + +``` + +Call buttons render inside [MessageHeader](/components/message-header) when calling is enabled. @@ -42,7 +50,7 @@ The React UI Kit auto-detects the SDK and activates calling features. [CallButto ### Incoming Call -The [Incoming Call](/ui-kit/react/incoming-call) component displays a call screen when a call is received, showing caller info with accept/reject options. +The [Incoming Call](/components/incoming-call) component displays a call screen when a call is received, showing caller info with accept/reject options. @@ -50,7 +58,7 @@ The [Incoming Call](/ui-kit/react/incoming-call) component displays a call scree ### Outgoing Call -The [Outgoing Call](/ui-kit/react/outgoing-call) component displays an outgoing call screen with recipient info and call status. Transitions to the ongoing call screen when the receiver accepts. +The [Outgoing Call](/components/outgoing-call) component displays an outgoing call screen with recipient info and call status. Transitions to the ongoing call screen when the receiver accepts. @@ -58,7 +66,7 @@ The [Outgoing Call](/ui-kit/react/outgoing-call) component displays an outgoing ### Call Logs -The [Call Logs](/ui-kit/react/call-logs) component displays call history — caller, time, and duration. +The [Call Logs](/components/call-logs) component displays call history — caller, time, and duration. @@ -67,16 +75,16 @@ The [Call Logs](/ui-kit/react/call-logs) component displays call history — cal ## Next Steps - - Audio and video call buttons + + Message header with integrated call buttons - + Incoming call notifications and UI - + Call history and details - + Core chat features diff --git a/ui-kit/react/calling-integration.mdx b/ui-kit/react/calling-integration.mdx index 4760a85b9..2254bd0a8 100644 --- a/ui-kit/react/calling-integration.mdx +++ b/ui-kit/react/calling-integration.mdx @@ -1,28 +1,250 @@ --- title: "Calling Integration" -description: "Add voice and video calling to CometChat React UI Kit with Calls SDK installation, setup checks, and CallButtons verification." +description: "Step-by-step guide to integrate voice and video calling into your React app using CometChat UI Kit v7." --- -## Overview +## Goal -This guide walks you through adding voice and video calling capabilities to your React application using the CometChat UI Kit. +By the end of this guide you will have voice and video calling working in your React app — including the `CometChatCallButtons` component, incoming call notifications, and outgoing call screens. - -Make sure you've completed the [Getting Started](/ui-kit/react/react-js-integration) guide before proceeding. - +## Prerequisites -## Add the Calls SDK +- A working CometChat React UI Kit v7 setup (completed the [Quick Start](/ui-kit/react/quick-start)) +- `CometChatProvider` configured with valid credentials +- A CometChat plan that includes calling features enabled in your [dashboard](https://app.cometchat.com) -Install the CometChat Calls SDK: +## Step 1: Install the Calls SDK -```bash +The calling feature requires the optional `@cometchat/calls-sdk-javascript` peer dependency: + + + +```bash npm npm install @cometchat/calls-sdk-javascript ``` -## Verify Integration +```bash yarn +yarn add @cometchat/calls-sdk-javascript +``` + +```bash pnpm +pnpm add @cometchat/calls-sdk-javascript +``` + + + +This package provides the WebRTC layer for voice and video calls. It is loaded lazily by the UI Kit — no additional bundle cost until calling is actually used. + +## Step 2: Enable calling in CometChatProvider + +Set the `callingEnabled` prop to `true` on your `CometChatProvider`: + +```tsx +import { CometChatProvider } from "@cometchat/chat-uikit-react"; +import "@cometchat/chat-uikit-react/styles"; + +function App() { + return ( + + + + ); +} +``` + +When `callingEnabled` is `true`, the UI Kit: +- Registers the `CallingPlugin` for call-related message rendering +- Lazy-loads call components (`CometChatIncomingCall`, `CometChatOutgoingCall`, `CometChatOngoingCall`) only when needed +- Enables the `CometChatCallButtons` component to initiate calls + +When `callingEnabled` is `false` (the default), call components are not loaded and `CometChatCallButtons` renders nothing. + +## Step 3: Configure call settings + +The Calls SDK uses the same `appId` and `region` as your chat SDK — no separate configuration is needed. `CometChatProvider` passes these credentials to the Calls SDK automatically when `callingEnabled` is `true`. + +If your app uses a dedicated calling app ID (separate from the chat app ID), pass it via the `config` prop: + +```tsx + + + +``` + +In most cases the chat and calling app IDs are the same, so this extra configuration is not needed. + +## Step 4: Add Call Buttons via CometChatMessageHeader + +`CometChatMessageHeader` automatically renders voice and video call buttons when `callingEnabled` is `true` on your provider. No extra configuration needed — just render the header with a `user` or `group`: + +```tsx +import { CometChat } from "@cometchat/chat-sdk-javascript"; +import { + CometChatMessageHeader, + CometChatMessageList, + CometChatMessageComposer, +} from "@cometchat/chat-uikit-react"; + +function ChatPanel({ user }: { user: CometChat.User }) { + return ( +
+ + + +
+ ); +} +``` + +The header shows call buttons by default. To hide them, use `hideVoiceCallButton` or `hideVideoCallButton`: + +```tsx + +``` + +For group calls, pass the `group` prop instead: + +```tsx + +``` + + +`CometChatMessageHeader.CallButtons` is a sub-component of `CometChatMessageHeader`. It is not a standalone component — you don't need to import or render it separately. + + +## Step 5: Verify with a voice call + +With the setup complete, test a voice call: + +1. Open your app with two different users in separate browser tabs +2. Click the **voice call** button (phone icon) in the chat header +3. The caller sees the `CometChatOutgoingCall` screen with a "Calling..." indicator +4. The receiver sees the `CometChatIncomingCall` overlay with accept/reject buttons +5. Once accepted, both users enter the `CometChatOngoingCall` view with live audio + +```tsx +import { useState } from "react"; +import { CometChat } from "@cometchat/chat-sdk-javascript"; +import { + CometChatProvider, + CometChatConversations, + CometChatMessageHeader, + CometChatMessageList, + CometChatMessageComposer, +} from "@cometchat/chat-uikit-react"; +import "@cometchat/chat-uikit-react/styles"; + +export default function App() { + const [user, setUser] = useState(null); + + const handleConversationClick = (conversation: CometChat.Conversation) => { + const conversationWith = conversation.getConversationWith(); + if (conversationWith instanceof CometChat.User) { + setUser(conversationWith); + } + }; + + return ( + +
+
+ +
+
+ {user && ( + <> + + + + + )} +
+
+
+ ); +} +``` + +## Step 6: Verify with a video call + +Video calls work identically — click the **video call** button (camera icon) instead. The `CometChatOngoingCall` component renders a full video interface with: + +- Local and remote video streams +- Mute/unmute audio toggle +- Camera on/off toggle +- End call button + +No additional configuration is needed to switch between audio-only and video calls. The call type is determined by which button the user clicks. + +## Step 7: Handle incoming and outgoing calls + +`CometChatIncomingCall` and `CometChatOutgoingCall` are automatically rendered by the UI Kit when `callingEnabled` is `true`. They listen for SDK call events via `SDKBridgeProvider` and display themselves as overlays when a call is initiated or received. + +You do not need to render these components manually — they are managed internally. However, you can customize their behavior with callbacks: + +```tsx +import { + CometChatProvider, + CometChatIncomingCall, + CometChatOutgoingCall, +} from "@cometchat/chat-uikit-react"; + +function App() { + return ( + + {/* These override the default auto-rendered call screens */} + console.log("Call accepted:", call)} + onReject={(call) => console.log("Call rejected:", call)} + /> + console.log("Call cancelled:", call)} + /> + + + ); +} +``` + +## Summary + +| Step | Action | +|------|--------| +| 1 | Install `@cometchat/calls-sdk-javascript` | +| 2 | Set `callingEnabled={true}` on `CometChatProvider` | +| 3 | (Optional) Configure separate calling app settings via `config` prop | +| 4 | Add `CometChatCallButtons` with a `user` or `group` prop | +| 5 | Test voice calls between two users | +| 6 | Test video calls between two users | +| 7 | (Optional) Customize incoming/outgoing call handlers | -After adding the dependency, the React UI Kit will automatically detect it and activate calling features. You will see [CallButtons](/ui-kit/react/call-buttons) rendered in the [MessageHeader](/ui-kit/react/message-header) component. +## Next Steps - - - +- [Message Header](/ui-kit/react/components/message-header) — full props reference including call button visibility +- [Call Logs](/ui-kit/react/components/call-logs) — display call history +- [CometChatProvider](/ui-kit/react/cometchat-provider) — all provider configuration options diff --git a/ui-kit/react/calling-overview.mdx b/ui-kit/react/calling-overview.mdx new file mode 100644 index 000000000..1bb9ac31e --- /dev/null +++ b/ui-kit/react/calling-overview.mdx @@ -0,0 +1,216 @@ +--- +title: "Calling Overview" +description: "Add voice and video calling to your app with the optional calls SDK, the callingEnabled flag, lazy-loaded call components, and the CallingPlugin." +--- + +## Overview + +Voice and video calling in CometChat React UI Kit v7 is entirely **opt-in**. The calling functionality is delivered through an optional peer dependency (`@cometchat/calls-sdk-javascript`), a feature flag (`callingEnabled`), and a dedicated `CallingPlugin` — all wired through the same provider and plugin system that powers the rest of the UI Kit. + +When calling is disabled (the default), no call-related code is included in your bundle. When enabled, call components are lazy-loaded on demand (Tier 2), keeping your initial bundle lean regardless of whether you use calling. + +**Key points:** + +- The calls SDK is an **optional peer dependency** — install it only if you need calling +- The `callingEnabled` prop on `CometChatProvider` gates all call functionality +- Call UI components (`CometChatIncomingCall`, `CometChatOutgoingCall`, `CometChatOngoingCall`, `CometChatCallLogs`) are Tier 2 lazy-loaded +- The `CallingPlugin` renders call message bubbles in the message list + +## Optional Peer Dependency + +The calling feature requires `@cometchat/calls-sdk-javascript` as an optional peer dependency. It is **not** bundled with the UI Kit — you install it separately only when you need voice or video calling. + +```bash +# npm +npm install @cometchat/calls-sdk-javascript + +# yarn +yarn add @cometchat/calls-sdk-javascript + +# pnpm +pnpm add @cometchat/calls-sdk-javascript +``` + +If the package is not installed and `callingEnabled` is set to `true`, the provider will log a warning at initialization time and calling features will be unavailable. + + +The calls SDK handles the WebRTC layer, call session management, and media device access. The UI Kit's calling components are a thin React layer on top of this SDK. + + +## The `callingEnabled` Flag + +The `callingEnabled` prop on `CometChatProvider` is the single toggle that activates all calling functionality: + +```tsx +import { CometChatProvider } from "@cometchat/chat-uikit-react"; +import "@cometchat/chat-uikit-react/styles"; + +function App() { + return ( + + + + ); +} +``` + +### What `callingEnabled` controls + +| When `callingEnabled` is... | Behavior | +|---|---| +| `false` (default) | No call SDK initialization, no call listeners attached, no call components loaded, `CometChatCallButtons` renders nothing | +| `true` | Calls SDK is initialized, SDK call listeners are attached in `SDKBridgeProvider`, call components are lazily available, `CometChatCallButtons` renders voice/video buttons | + +Internally, when `callingEnabled` is `true`: + +1. `CometChatProvider` initializes the calls SDK via `CometChatCalls.init()` +2. `SDKBridgeProvider` attaches call-related SDK listeners (`onIncomingCallReceived`, `onOutgoingCallAccepted`, `onOutgoingCallRejected`, `onCallEndedMessageReceived`) +3. Call components become available for lazy loading +4. The `CallingPlugin` (if registered) renders call message bubbles + +## Lazy-Loading of Call Components + +All call UI components are **Tier 2 lazy-loaded** — they are only fetched from the server when `callingEnabled` is `true` AND the component is needed. This means zero impact on bundle size for apps that don't use calling. + +### Tier 2 Components + +| Component | When Loaded | Purpose | +|---|---|---| +| `CometChatIncomingCall` | When an incoming call event is received | Full-screen overlay with accept/reject buttons | +| `CometChatOutgoingCall` | When the user initiates a call | Full-screen overlay with cancel button | +| `CometChatOngoingCall` | When a call is accepted (either direction) | Active call view with controls (mute, video toggle, end) | +| `CometChatCallLogs` | When the user navigates to call history | Paginated list of past calls | + +### How Lazy Loading Works + +Each Tier 2 component has a `.lazy.ts` file that provides the default export required by `React.lazy()`: + +```typescript +// CometChatIncomingCall.lazy.ts +export { CometChatIncomingCall as default } from './CometChatIncomingCall'; +``` + +The provider conditionally loads these components only when `callingEnabled` is `true`: + +```typescript +import { lazy, Suspense } from 'react'; + +// Only created when callingEnabled is true +const LazyCometChatIncomingCall = lazy( + () => import('./CometChatIncomingCall/CometChatIncomingCall.lazy') +); + +// Rendered inside CometChatProvider when calling is enabled +{callingEnabled && ( + + + +)} +``` + + +`CometChatIncomingCall` and `CometChatOutgoingCall` are managed internally by `CometChatProvider` — they auto-display based on SDK call events. You don't render them manually unless you need custom behavior. + + +### Bundle Impact + +| Scenario | Call Code in Bundle | +|---|---| +| `callingEnabled={false}` (default) | 0 KB — no call code loaded | +| `callingEnabled={true}`, no active call | ~2 KB (listener setup only) | +| `callingEnabled={true}`, call in progress | Full call component chunk loaded on demand | + +## CallingPlugin Registration + +The `CallingPlugin` is a `CometChatMessagePlugin` that renders call message bubbles (missed call, call ended, call rejected) in the message list and provides conversation list previews for call messages. + +### Registering the Plugin + +Add `CometChatCallingPlugin` to the `plugins` array: + +```tsx +import { CometChatProvider } from "@cometchat/chat-uikit-react"; +import { defaultPlugins } from "@cometchat/chat-uikit-react/plugins/core"; +import { CometChatCallingPlugin } from "@cometchat/chat-uikit-react/plugins/calling"; + +function App() { + return ( + + + + ); +} +``` + +### What CallingPlugin Handles + +| Capability | Details | +|---|---| +| `messageTypes` | `['meeting']` | +| `messageCategories` | `['call']` | +| `renderBubble` | Renders `CometChatCallBubble` showing call type, duration, and status | +| `getOptions` | Returns empty array (call messages have no context menu) | +| `getLastMessagePreview` | Returns previews like `📞 Voice call` or `📹 Video call (2:34)` | + +### Call Bubble Rendering + +The `CometChatCallBubble` component (rendered by the plugin) displays: + +- Call type icon (voice or video) +- Call status (missed, rejected, ended, ongoing) +- Call duration (for completed calls) +- Caller/receiver information + +```tsx +// The plugin handles this internally via renderBubble. +// You don't render CometChatCallBubble directly. +// It appears automatically in CometChatMessageList for call messages. +``` + +## Architecture Diagram + +``` +┌─────────────────────────────────────────────────────────────┐ +│ CometChatProvider (callingEnabled={true}) │ +│ │ +│ ┌────────────────────────────────────────────────────────┐ │ +│ │ SDKBridgeProvider │ │ +│ │ • Attaches call listeners │ │ +│ │ • Emits call/incoming, call/outgoing events │ │ +│ └────────────────────────┬───────────────────────────────┘ │ +│ │ │ +│ ┌───────────────┼───────────────┐ │ +│ ▼ ▼ ▼ │ +│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │ +│ │ IncomingCall │ │ OutgoingCall │ │ OngoingCall │ │ +│ │ (Tier 2 lazy)│ │ (Tier 2 lazy)│ │ (Tier 2 lazy) │ │ +│ └──────────────┘ └──────────────┘ └──────────────┘ │ +│ │ +│ ┌────────────────────────────────────────────────────────┐ │ +│ │ PluginRegistry │ │ +│ │ • CallingPlugin → renders CometChatCallBubble │ │ +│ │ • Handles messageType: 'meeting', category: 'call' │ │ +│ └────────────────────────────────────────────────────────┘ │ +└─────────────────────────────────────────────────────────────┘ +``` + +## Related Pages + +- [Calling Integration Guide](/ui-kit/react/calling-integration) — Step-by-step setup instructions +- [Call Buttons](/ui-kit/react/components/call-buttons) — Voice and video call trigger buttons +- [Call Logs](/ui-kit/react/components/call-logs) — Paginated call history list +- [Incoming Call](/ui-kit/react/components/incoming-call) — Incoming call overlay component +- [Outgoing Call](/ui-kit/react/components/outgoing-call) — Outgoing call overlay component +- [CometChatProvider](/ui-kit/react/cometchat-provider) — Root provider configuration +- [Plugin System](/ui-kit/react/plugin-system) — How plugins work diff --git a/ui-kit/react/cometchat-provider.mdx b/ui-kit/react/cometchat-provider.mdx new file mode 100644 index 000000000..fb341f58e --- /dev/null +++ b/ui-kit/react/cometchat-provider.mdx @@ -0,0 +1,317 @@ +--- +title: "CometChatProvider" +description: "The root provider that initializes the CometChat SDK, manages authentication, and composes all internal contexts for the React UI Kit." +--- + +## Overview + +Every CometChat component must be rendered inside a provider tree that supplies theme, locale, plugin registry, and real-time events. The UI Kit offers two ways to set this up: + +| Approach | Best for | Init & login | Provider setup | +| --- | --- | --- | --- | +| **CometChatProvider** (recommended) | Most apps | Automatic — just pass credentials | Single component wraps everything | +| **Individual providers** | Advanced control (custom login flows, multiple instances) | Manual — call `CometChatUIKit.init()` + `login()` yourself | Compose `ThemeProvider`, `LocaleProvider`, `EventsProvider`, `PluginRegistryContext` manually | + +--- + +## Approach 1: CometChatProvider (Recommended) + +`CometChatProvider` is a single component that handles SDK initialization, user login, plugin registration, theming, localization, and real-time events — all declaratively via props. + +```tsx +import { CometChatProvider, CometChatConversations } from "@cometchat/chat-uikit-react"; +import "@cometchat/chat-uikit-react/styles"; + +function App() { + return ( + + + + ); +} +``` + +That's it. No `CometChatUIKit.init()`, no `UIKitSettingsBuilder`, no manual login. The provider handles the full lifecycle: + +1. Builds `UIKitSettings` from your props +2. Calls `CometChatUIKit.init(settings)` internally +3. Logs in the user (via `uid` + `authKey`, or `authToken`) +4. Sets up the plugin registry (default plugins included automatically) +5. Provides theme, locale, and event contexts to all child components + +### Props + +| Prop | Type | Required | Default | Description | +| --- | --- | --- | --- | --- | +| `appId` | `string` | Yes* | — | CometChat app ID from the dashboard | +| `region` | `string` | Yes* | — | App region (`"us"`, `"eu"`, `"in"`) | +| `authToken` | `string` | — | — | Auth token for production login (server-generated) | +| `uid` | `string` | — | — | User UID for development login (used with `authKey`) | +| `authKey` | `string` | — | — | Auth key for development login (used with `uid`) | +| `settings` | `UIKitSettings` | — | — | Pre-built settings object for full control. When provided, `appId`/`region`/`callingEnabled`/`plugins` props are ignored | +| `callingEnabled` | `boolean` | No | `false` | Enable voice/video calling (requires `@cometchat/calls-sdk-javascript`) | +| `plugins` | `CometChatMessagePlugin[]` | No | — | Additional plugins beyond the defaults | +| `theme` | `"light" \| "dark"` | No | `"light"` | Active theme | +| `locale` | `string` | No | `"en-us"` | Language code for i18n | +| `config` | `CometChatGlobalConfig` | No | `{}` | Global flags (`hideReceipts`, `hideUserStatus`, etc.) | +| `onError` | `(error: Error) => void` | No | — | Called on init or login failure | +| `onLoginSuccess` | `(user: CometChat.User) => void` | No | — | Called when login succeeds | + +*Required unless `settings` is provided. + +### Authentication + +Provide one of: +- `authToken` — for production (generated server-side via REST API) +- `uid` + `authKey` — for development/testing only + +```tsx +{/* Production */} + + +{/* Development */} + +``` + +### Advanced: Pre-built Settings + +For full control over SDK configuration (presence subscription mode, custom hosts, storage mode), pass a `UIKitSettings` object: + +```tsx +import { CometChatProvider, UIKitSettingsBuilder } from "@cometchat/chat-uikit-react"; + +const settings = new UIKitSettingsBuilder() + .setAppId("YOUR_APP_ID") + .setRegion("us") + .setAuthKey("YOUR_AUTH_KEY") + .subscribePresenceForRoles(["admin", "support"]) + .setCallingEnabled(true) + .setAutoEstablishSocketConnection(true) + .build(); + +function App() { + return ( + + + + ); +} +``` + +### With Calling Enabled + +```tsx + + + +``` + +### With Custom Theme and Locale + +```tsx + + + +``` + +### With Additional Plugins + +Default plugins (text, image, file, audio, video) are always included. Pass additional plugins via the `plugins` prop: + +```tsx +import { CometChatProvider } from "@cometchat/chat-uikit-react"; +import { CometChatAIPlugin } from "@cometchat/chat-uikit-react/plugins/ai"; + + + + +``` + +### Accessing the Logged-In User + +Inside your components (children of `CometChatProvider`), access the logged-in user via the `useLoggedInUser()` hook or `CometChatUIKit.getLoggedInUser()`: + +```tsx +import { useLoggedInUser } from "@cometchat/chat-uikit-react"; + +function MyComponent() { + const loggedInUser = useLoggedInUser(); + + if (!loggedInUser) return
Logging in...
; + + return
Welcome, {loggedInUser.getName()}
; +} +``` + +--- + +## Approach 2: Individual Providers (Advanced) + +For apps that need custom login flows, multiple CometChat instances, or fine-grained control over the provider tree, you can initialize manually and compose providers yourself. + +### Step 1: Initialize and Login + +Call `CometChatUIKit.init()` and `CometChatUIKit.login()` before rendering: + +```tsx title="src/main.tsx" +import ReactDOM from "react-dom/client"; +import { CometChatUIKit, UIKitSettingsBuilder } from "@cometchat/chat-uikit-react"; +import App from "./App"; + +const settings = new UIKitSettingsBuilder() + .setAppId("YOUR_APP_ID") + .setRegion("us") + .setAuthKey("YOUR_AUTH_KEY") + .subscribePresenceForAllUsers() + .setCallingEnabled(true) + .build(); + +CometChatUIKit.init(settings).then(async () => { + // Login — use loginWithAuthToken() in production + await CometChatUIKit.login("cometchat-uid-1"); + ReactDOM.createRoot(document.getElementById("root")!).render(); +}); +``` + +### Step 2: Compose Providers + +After init and login, wrap your app with the individual providers: + +```tsx title="src/App.tsx" +import { + CometChatThemeProvider, + CometChatEventsProvider, + LocaleProvider, + CometChatPluginRegistryContext, + CometChatPluginRegistry, + defaultPlugins, +} from "@cometchat/chat-uikit-react"; +import "@cometchat/chat-uikit-react/styles"; + +const pluginRegistry = new CometChatPluginRegistry(defaultPlugins); + +function App() { + return ( + + + + + + + + + + ); +} +``` + +### When to Use This Approach + +- **Custom login flows** — your app has its own auth system and you need to control when login happens +- **Multiple chat instances** — you need separate plugin registries or themes for different parts of the app +- **Gradual migration** — you're migrating from v6 and want to keep the imperative init pattern temporarily +- **Server-side rendering** — you need to defer initialization to a specific lifecycle point + + +Even with individual providers, `CometChatUIKit.init()` must be called before rendering any CometChat components. The individual providers do not handle initialization — they only provide React context. + + +--- + +## Internal Architecture + +`CometChatProvider` composes these internal providers in order: + +``` +CometChatProvider + └─ PluginRegistryContext — plugin registry from CometChatUIKit + └─ GlobalConfigProvider — hideReceipts, hideUserStatus, etc. + └─ ThemeProvider — data-theme attribute + CSS variables + └─ LocaleProvider — i18n translations + └─ EventsProvider — SDK listeners + UI events (mounted after login) + └─ {children} +``` + +The `EventsProvider` only mounts after login succeeds. Before that, children render without real-time event subscriptions (which is correct since there's no authenticated session to listen on). + +--- + +## Next.js App Router + +`CometChatProvider` uses browser APIs internally, so it must be placed inside a Client Component: + +```tsx title="app/providers.tsx" +"use client"; + +import { CometChatProvider } from "@cometchat/chat-uikit-react"; +import "@cometchat/chat-uikit-react/styles"; + +export function ChatProviders({ children }: { children: React.ReactNode }) { + return ( + + {children} + + ); +} +``` + +--- + +## Migration from v6 + +In v6, initialization was always imperative: + +```tsx title="v6 (before)" +import { CometChatUIKit, UIKitSettingsBuilder } from "@cometchat/chat-uikit-react"; + +const settings = new UIKitSettingsBuilder() + .setAppId("APP_ID") + .setRegion("REGION") + .setAuthKey("AUTH_KEY") + .build(); + +await CometChatUIKit.init(settings); +await CometChatUIKit.login("USER_ID"); +``` + +```tsx title="v7 (after)" + + + +``` + +Key differences: +- No manual `init()` or `login()` calls needed +- No `UIKitSettingsBuilder` required for basic usage +- Default plugins are included automatically +- Theme and locale are props, not separate configuration steps +- Real-time events are managed internally (no RxJS, no manual listener setup) diff --git a/ui-kit/react/components-overview.mdx b/ui-kit/react/components-overview.mdx index 4418f1c8d..9f5c20a09 100644 --- a/ui-kit/react/components-overview.mdx +++ b/ui-kit/react/components-overview.mdx @@ -1,92 +1,192 @@ --- title: "Overview" -description: "Browse all prebuilt UI components in the CometChat React UI Kit — conversations, messages, users, groups, calls, search, and AI." +description: "Understand the component architecture, usage patterns, and all available components in the CometChat React UI Kit." --- - - -| Field | Value | -| --- | --- | -| Package | `@cometchat/chat-uikit-react` | -| Required setup | `CometChatUIKit.init()` + `CometChatUIKit.login()` before rendering any component | -| Callback actions | `on={(param) => {}}` | -| Data filtering | `RequestBuilder={new CometChat.RequestBuilder()}` | -| Toggle features | `hide={true}` or `show={true}` | -| Custom rendering | `View={() => JSX}` | -| CSS overrides | Target `.cometchat-` class in global CSS | -| Calling | Requires separate `@cometchat/calls-sdk-javascript` package | - - - ## Architecture -The UI Kit is a set of independent components that compose into chat layouts. A typical two-panel layout uses four core components: +The UI Kit provides a set of independent, composable React components that wire together into complete chat layouts. A typical two-panel layout uses four core components: -- **CometChatConversations** — sidebar listing recent conversations (users and groups) -- **CometChatMessageHeader** — toolbar showing avatar, name, online status, and typing indicator +- **CometChatConversations** — sidebar listing recent conversations +- **CometChatMessageHeader** — toolbar showing avatar, name, status, and typing indicator - **CometChatMessageList** — scrollable message feed with reactions, receipts, and threads - **CometChatMessageComposer** — rich text input with attachments, mentions, and voice notes -Data flow: selecting a conversation in CometChatConversations yields a `CometChat.User` or `CometChat.Group` object. That object is passed as a prop (`user` or `group`) to CometChatMessageHeader, CometChatMessageList, and CometChatMessageComposer. The message components use the SDK internally — CometChatMessageComposer sends messages, CometChatMessageList receives them via real-time listeners. +Data flow: selecting a conversation yields a `CometChat.User` or `CometChat.Group` object. Pass that object as a prop (`user` or `group`) to the message components. They handle SDK calls internally — the composer sends messages, the list receives them via real-time listeners. + +All components must be rendered inside a `` which initializes the SDK connection and provides shared context (theme, locale, events). + +{/* TODO:IMAGE - Two-panel chat layout: Conversations sidebar on left, MessageHeader + MessageList + MessageComposer on right */} + +```tsx +import { + CometChatProvider, + CometChatConversations, + CometChatMessageHeader, + CometChatMessageList, + CometChatMessageComposer, +} from "@cometchat/chat-uikit-react"; + +function ChatApp() { + const [user, setUser] = useState(); + + return ( + +
+ setUser(conv.getConversationWith())} /> +
+ + + +
+
+
+ ); +} +``` + +--- + +## Flat API + +Every feature component can be rendered in a single line. Pass props directly, the component handles its own layout internally. + +```tsx + +``` + +This is the quickest way to get started. The component renders all its default sub-components (header, list, empty state, loading state, etc.) automatically. + +--- + +## Compound Composition -Components communicate through a publish/subscribe event bus (`CometChatMessageEvents`, `CometChatConversationEvents`, `CometChatGroupEvents`, etc.). A component emits events that other components or application code can subscribe to without direct references. See [Events](/ui-kit/react/events) for the full list. +For full layout control, use the compound pattern. Each feature component is a namespace with sub-components: + +```tsx + + {/* Only render what you need, and omit sub-components to hide them */} + + + +``` -Each component accepts callback props (`on`), view slot props (`View`) for replacing UI sections, `RequestBuilder` props for data filtering, and CSS variable overrides on `.cometchat-` classes. +Key principles: +- **Root** initializes state, fetches data, and provides context to children. +- **Sub-components** read from context and render when their state is active. +- **Omit a sub-component** to hide it, no boolean props needed. +- **Add custom elements** anywhere inside Root alongside the sub-components. + +Both APIs produce the same result. The flat API is shorthand for rendering Root with all sub-components in their default order. --- -## Component Catalog +## Component Categories + +Components are organized into three categories: + +### Feature Components + +Feature components integrate with the CometChat SDK for data fetching, real-time events, and state management. They follow the compound pattern and support both flat and compound APIs. + +Feature components: +- Own their data lifecycle (fetch, paginate, refresh) +- Subscribe to real-time SDK events (new messages, presence changes, typing indicators) +- Manage complex state via hooks and reducers +- Provide context to their sub-components + +### Base Components + +Base components are pure UI building blocks with no SDK integration. They accept props and render UI — no network calls, no real-time events. Feature components compose these internally. + +Base components use a plain namespace object (compound sub-components) but don't have the callable flat API shorthand. + +Examples: Avatar, Button, Date, ContextMenu, SearchBar, ConfirmDialog, Popover, MediaRecorder, MessageBubble, Reactions. + +### Bubble Components (Plugins) -All components are imported from `@cometchat/chat-uikit-react`. +Message bubble components (TextBubble, ImageBubble, FileBubble, AudioBubble, VideoBubble, StickerBubble, PollBubble, etc.) are part of the **Plugin system**. Each plugin handles a specific message type and provides the bubble component that renders it. + +Bubble components are documented in the [Plugins](/plugins/overview) section alongside their parent plugin. See [Plugins Overview](/plugins/overview) for how to customize message rendering. + +--- + +## Feature Components + +{/* TODO:STORYBOOK - Link to Storybook component gallery showing all feature components */} + +All feature components are imported from `@cometchat/chat-uikit-react`. ### Conversations and Lists -| Component | Purpose | Key Props | Page | -| --- | --- | --- | --- | -| CometChatConversations | Scrollable list of recent conversations | `conversationsRequestBuilder`, `onItemClick`, `onError` | [Conversations](/ui-kit/react/conversations) | -| CometChatUsers | Scrollable list of users | `usersRequestBuilder`, `onItemClick`, `onError` | [Users](/ui-kit/react/users) | -| CometChatGroups | Scrollable list of groups | `groupsRequestBuilder`, `onItemClick`, `onError` | [Groups](/ui-kit/react/groups) | -| CometChatGroupMembers | Scrollable list of group members | `group`, `groupMemberRequestBuilder`, `onItemClick` | [Group Members](/ui-kit/react/group-members) | +| Component | Purpose | Page | +| --- | --- | --- | +| `CometChatConversations` | Scrollable list of recent conversations with real-time updates | [Conversations](/components/conversations) | +| `CometChatUsers` | Searchable list of users with selection support | [Users](/components/cometchat-users) | +| `CometChatGroups` | Searchable list of groups with selection support | [Groups](/components/cometchat-groups) | +| `CometChatGroupMembers` | List of group members with role-based actions | [Group Members](/components/cometchat-group-members) | ### Messages -| Component | Purpose | Key Props | Page | -| --- | --- | --- | --- | -| CometChatMessageHeader | Toolbar with avatar, name, status, typing indicator | `user`, `group`, `enableAutoSummaryGeneration` | [Message Header](/ui-kit/react/message-header) | -| CometChatMessageList | Scrollable message list with reactions, receipts, threads | `user`, `group`, `messagesRequestBuilder`, `goToMessageId` (string) | [Message List](/ui-kit/react/message-list) | -| CometChatMessageComposer | Rich text input with attachments, mentions, voice notes | `user`, `group`, `onSendButtonClick`, `placeholderText` | [Message Composer](/ui-kit/react/message-composer) | -| CometChatMessageTemplate | Pre-defined structure for custom message bubbles | `type`, `category`, `contentView`, `headerView`, `footerView` | [Message Template](/ui-kit/react/message-template) | -| CometChatThreadHeader | Parent message bubble and reply count for threaded view | `parentMessage`, `onClose`, `hideReceipts`, `textFormatters` | [Thread Header](/ui-kit/react/thread-header) | +| Component | Purpose | Page | +| --- | --- | --- | +| `CometChatMessageHeader` | Toolbar with avatar, name, status, typing indicator, and call buttons | [Message Header](/components/message-header) | +| `CometChatMessageList` | Scrollable message feed with plugin-based bubble rendering | [Message List](/components/message-list) | +| `CometChatMessageComposer` | Rich text input with attachments, emoji, voice recording, and formatting | [Message Composer](/components/message-composer) | +| `CometChatThreadHeader` | Parent message bubble and reply count for threaded conversations | [Thread Header](/components/thread-header) | +| `CometChatMessageInformation` | Message delivery and read receipt details panel | [Message Information](/components/message-information) | ### Calling -| Component | Purpose | Key Props | Page | -| --- | --- | --- | --- | -| CometChatCallButtons | Voice and video call initiation buttons | `user`, `group`, `onVoiceCallClick`, `onVideoCallClick` | [Call Buttons](/ui-kit/react/call-buttons) | -| CometChatIncomingCall | Incoming call notification with accept/decline | `call`, `onAccept(call)`, `onDecline(call)` | [Incoming Call](/ui-kit/react/incoming-call) | -| CometChatOutgoingCall | Outgoing call screen with cancel control | `call`, `onCloseClicked` | [Outgoing Call](/ui-kit/react/outgoing-call) | -| CometChatCallLogs | Scrollable list of call history | `callLogsRequestBuilder`, `onItemClick` | [Call Logs](/ui-kit/react/call-logs) | +| Component | Purpose | Page | +| --- | --- | --- | +| `CometChatCallButtons` | Voice and video call initiation buttons | [Call Buttons](/components/call-buttons) | +| `CometChatIncomingCall` | Incoming call notification with accept/decline | [Incoming Call](/components/incoming-call) | +| `CometChatOutgoingCall` | Outgoing call screen with cancel control | [Outgoing Call](/components/outgoing-call) | +| `CometChatCallLogs` | Scrollable list of call history | [Call Logs](/components/call-logs) | ### Search and AI -| Component | Purpose | Key Props | Page | -| --- | --- | --- | --- | -| CometChatSearch | Real-time search across conversations and messages | `onConversationClicked(conversation, searchKeyword?)`, `onMessageClicked(message, searchKeyword?)`, `uid`, `guid`, `textFormatters` | [Search](/ui-kit/react/search) | -| CometChatAIAssistantChat | AI agent chat with streaming, suggestions, history | `user`, `onSendButtonClick(message, previewMessageMode?)`, `aiAssistantTools` | [AI Assistant Chat](/ui-kit/react/ai-assistant-chat) | +| Component | Purpose | Page | +| --- | --- | --- | +| `CometChatSearch` | Unified search across conversations and messages | [Search](/components/search) | +| `CometChatAIAssistantChat` | AI agent chat with streaming, suggestions, and history | [AI Assistant](/components/ai-assistant) | -## Component API Pattern +--- + +## Base Components -All components share a consistent API surface. +Base components are imported from `@cometchat/chat-uikit-react`. They don't have individual doc pages — use the source types and Storybook for reference. -### Actions +{/* TODO:STORYBOOK - Link to Storybook base components category */} + +| Component | Purpose | +| --- | --- | +| `CometChatAvatar` | User/group avatar with image and initials fallback | +| `CometChatButton` | Styled button with icon, text, loading, and variant support | +| `CometChatDate` | Formatted date/time display with temporal bucketing | +| `CometChatContextMenu` | Options menu with top-row icons and overflow dropdown | +| `CometChatSearchBar` | Search input with clear button and keyboard handling | +| `CometChatActionSheet` | Bottom sheet with grouped action items | +| `CometChatConfirmDialog` | Confirmation dialog with customizable message and buttons | +| `CometChatChangeScope` | Group member role/scope change selector | +| `CometChatMessageBubble` | Message bubble container with alignment, receipts, and options | +| `CometChatReactions` | Reaction chips bar with reactor list popover | +| `CometChatReactionList` | Full reactor list with tabs and pagination | +| `CometChatFullScreenViewer` | Full-screen image/media viewer with download | +| `CometChatMediaRecorder` | Audio recording with timer, preview, and submit | -Actions control component behavior. They split into two categories: +--- + +## Component API Pattern -**Predefined Actions** are built into the component and execute automatically on user interaction (e.g., clicking send dispatches the message). No configuration needed. +All components share a consistent API surface for customization. -**User-Defined Actions** are callback props that fire on specific events. Override them to customize behavior: +### Actions (Callbacks) -```tsx lines +Callback props fire on user interactions. Override them to customize behavior: + +```tsx openThreadPanel(message)} @@ -94,74 +194,67 @@ Actions control component behavior. They split into two categories: /> ``` -### Events - -Events enable decoupled communication between components. A component emits events that other parts of the application can subscribe to without direct references. +### Filters (RequestBuilder) -```tsx lines -import { CometChatMessageEvents } from "@cometchat/chat-uikit-react"; +List components accept `RequestBuilder` props to control which data loads: -const sub = CometChatMessageEvents.ccMessageSent.subscribe((message) => { - // react to sent message -}); - -// cleanup -sub?.unsubscribe(); +```tsx + ``` -Each component page documents its emitted events in the Events section. +Pass the builder instance — not the result of `.build()`. -### Filters +### View Props -List-based components accept `RequestBuilder` props to control which data loads: +View props replace the visual content inside a component slot while keeping the default behavior wired: -```tsx lines -} + headerView={} + auxiliaryButtonView={} /> ``` -### Custom View Slots +For deeper control, use compound composition to replace entire slots including their behavior. -Components expose named view slots to replace sections of the default UI: +### CSS Styling -```tsx lines -} - subtitleView={} - leadingView={} -/> -``` +Components use CSS custom properties (design tokens). Override them on the `.cometchat` root or on component-specific selectors: -### CSS Overrides - -Every component has a root CSS class (`.cometchat-`) for style customization: +```css +.cometchat { + --cometchat-primary-color: #6851d6; + --cometchat-font-family: "Inter", sans-serif; +} -```css lines -.cometchat-message-list .cometchat-text-bubble__body-text { - font-family: "SF Pro"; +.cometchat-message-list { + --cometchat-background-color-01: #fafafa; } ``` +Component class names follow BEM convention: `.cometchat-component-name__element--modifier`. + --- ## Next Steps - - Chat features included out of the box + + Customize colors, fonts, and spacing with CSS variables - - Customize colors, fonts, and styles + + Customize message rendering with the plugin system - - Add-on features like polls, stickers, and translation + + Subscribe to real-time events across components - + Task-oriented tutorials for common patterns diff --git a/ui-kit/react/components/action-sheet.mdx b/ui-kit/react/components/action-sheet.mdx new file mode 100644 index 000000000..3d379bc70 --- /dev/null +++ b/ui-kit/react/components/action-sheet.mdx @@ -0,0 +1,490 @@ +--- +title: "Action Sheet" +description: "A modal overlay that presents a list or grid of contextual actions the user can take, such as attaching files, sharing media, or launching extensions." +--- + + +```json +{ + "component": "CometChatActionSheet", + "package": "@cometchat/chat-uikit-react", + "import": "import { CometChatActionSheet } from \"@cometchat/chat-uikit-react\";", + "cssImport": "import \"@cometchat/chat-uikit-react/css-variables.css\";", + "description": "A modal overlay that presents a list or grid of contextual actions the user can take.", + "cssRootClass": ".cometchat-action-sheet", + "subComponents": ["Root", "Header", "Layout", "Item"], + "props": { + "Root": { + "isOpen": { "type": "boolean", "default": "false" }, + "onClose": { "type": "() => void", "default": "undefined" }, + "layoutMode": { "type": "'list' | 'grid'", "default": "'list'" }, + "title": { "type": "string", "default": "undefined", "description": "Optional title displayed in the header." }, + "className": { "type": "string", "default": "undefined" }, + "children": { "type": "ReactNode", "default": "undefined" } + }, + "Header": { + "title": { "type": "string", "default": "undefined" }, + "onClose": { "type": "() => void", "default": "undefined" }, + "children": { "type": "ReactNode", "default": "undefined" } + }, + "Layout": { + "mode": { "type": "'list' | 'grid'", "default": "'list'" }, + "children": { "type": "ReactNode", "default": "undefined" } + }, + "Item": { + "item": { "type": "CometChatActionSheetItemData", "default": "undefined", "note": "Required." }, + "className": { "type": "string", "default": "undefined" } + } + }, + "types": { + "CometChatActionSheetItemData": { + "id": "string", + "title": "string", + "icon": "ReactNode (optional)", + "onClick": "() => void", + "subtitle": "string (optional)", + "disabled": "boolean (optional)", + "className": "string (optional)" + }, + "CometChatActionSheetLayoutMode": "'list' | 'grid'", + "CometChatActionSheetContextValue": { + "isOpen": "boolean", + "onClose": "() => void", + "layoutMode": "CometChatActionSheetLayoutMode" + } + } +} +``` + + +## Where It Fits + +`CometChatActionSheet` is a base component used by higher-level components like `CometChatMessageComposer` to present attachment options, and by `CometChatContextMenu` for contextual actions. It renders as a modal overlay with a backdrop, focus trap, and keyboard navigation. + +```tsx lines +import { CometChatActionSheet } from "@cometchat/chat-uikit-react"; +import "@cometchat/chat-uikit-react/css-variables.css"; +import { useState } from "react"; + +const actions = [ + { id: "image", title: "Attach Image", icon: , onClick: () => console.log("image") }, + { id: "video", title: "Attach Video", icon: , onClick: () => console.log("video") }, + { id: "file", title: "Attach File", icon: , onClick: () => console.log("file") }, +]; + +function ComposerWithSheet() { + const [open, setOpen] = useState(false); + + return ( +
+ + setOpen(false)}> + setOpen(false)} /> + + {actions.map((a) => ( + + ))} + + +
+ ); +} +``` + +## Minimal Render + +```tsx lines +import { CometChatActionSheet } from "@cometchat/chat-uikit-react"; +import "@cometchat/chat-uikit-react/css-variables.css"; + +function Demo() { + return ( + {}}> + + {} }} + /> + + + ); +} +``` + +Root CSS class: `.cometchat-action-sheet` + + +## Sub-Components + +`CometChatActionSheet` is a compound component with four sub-components: + +| Sub-component | Purpose | +| --- | --- | +| `Root` | Modal overlay container. Provides context, backdrop, focus trap, and keyboard handling. | +| `Header` | Optional header bar with title and close button. | +| `Layout` | Arranges items in `list` (vertical) or `grid` (icon grid) mode. | +| `Item` | A single action rendered as a button. | + +### Root + +The outermost wrapper. Controls open/close state, renders the backdrop, traps focus, and handles Escape, ArrowUp/ArrowDown, Home/End key navigation. + +```tsx lines + setOpen(false)}> + {/* Header, Layout, and Items go here */} + +``` + +### Header + +Renders a title and optional close button. Pass `children` for fully custom header content. + +```tsx lines + setOpen(false)} /> +``` + +### Layout + +Arranges child items. Defaults to `list` mode (vertical stack). Set `mode="grid"` for an icon grid. + + + +```tsx lines + + + + +``` + + +```tsx lines + + + + +``` + + + +### Item + +Renders a single action as a `
+ } +/> +``` + +## Actions and Events + +### Callback Props + +#### onSendButtonClick + +Called when a message is sent to the AI assistant. + +```tsx lines + { + console.log("Message sent:", message.getId()); + }} +/> +``` + +#### onError + +Called when an error occurs (fetch failure, SDK error, etc.). + +```tsx lines + { + console.error("AI chat error:", error); + }} +/> +``` + +## Lazy Loading + +`CometChatAIAssistantChat` is Tier 4 lazy — it's not included in the initial bundle. Load it on demand: + +```tsx lines +import { lazy, Suspense } from "react"; + +const LazyAIAssistantChat = lazy( + () => import("@cometchat/chat-uikit-react/plugins/ai/CometChatAIAssistantChat.lazy") +); + +// Preload on button hover/focus to reduce perceived latency +const preload = () => + import("@cometchat/chat-uikit-react/plugins/ai/CometChatAIAssistantChat.lazy"); + +function App() { + const [open, setOpen] = useState(false); + + return ( + <> + + + {open && ( + Loading...
}> + setOpen(false)} /> + + )} + + ); +} +``` + +## CSS Architecture + +The component uses CSS custom properties defined in `@cometchat/chat-uikit-react/css-variables.css`. + +### Key Selectors + +| Target | Selector | +| --- | --- | +| Root | `.cometchat-ai-assistant-chat` | +| Header | `.cometchat-ai-assistant-chat__header` | +| Message list wrapper | `.cometchat-ai-assistant-chat__message-list-wrapper` | +| Composer area | `.cometchat-ai-assistant-chat__composer-area` | +| Streaming (disabled) | `.cometchat-ai-assistant-chat__composer-area--streaming` | +| Empty state | `.cometchat-ai-assistant-chat__empty-state` | +| Suggestion pill | `.cometchat-ai-assistant-chat__suggestion-pill` | +| Stream bubble wrapper | `.cometchat-ai-assistant-chat__stream-bubble-wrapper` | +| Sidebar | `.cometchat-ai-assistant-chat__sidebar` | +| Sidebar overlay | `.cometchat-ai-assistant-chat__sidebar-overlay` | + +### Stream Message Bubble Selectors + +| Target | Selector | +| --- | --- | +| Root | `.cometchat-stream-message-bubble` | +| Thinking state | `.cometchat-stream-message-bubble__thinking` | +| Tool execution | `.cometchat-stream-message-bubble__tool-execution` | +| Content | `.cometchat-stream-message-bubble__content` | +| Error | `.cometchat-stream-message-bubble__error` | + +### AI Assistant Bubble Selectors + +| Target | Selector | +| --- | --- | +| Root | `.cometchat-ai-assistant-bubble` | +| Content | `.cometchat-ai-assistant-bubble__content` | +| Placeholder shimmer | `.cometchat-ai-assistant-bubble__placeholder` | + +### Tool Call Selectors + +| Target | Selector | +| --- | --- | +| Argument bubble root | `.cometchat-toolcall-argument-bubble` | +| Argument item | `.cometchat-toolcall-argument-bubble__item` | +| Result bubble root | `.cometchat-toolcall-result-bubble` | +| Result code | `.cometchat-toolcall-result-bubble__code` | + +## Props + +All props are optional unless noted otherwise. + +--- + +### user + +**Required.** The AI assistant user object. The component uses `user.getUid()` as the chat ID for streaming events. + +| | | +| --- | --- | +| Type | `CometChat.User` | +| Default | required | + +--- + +### streamingSpeed + +Delay in milliseconds between text content chunks. Lower values feel faster; higher values feel more natural. + +| | | +| --- | --- | +| Type | `number` | +| Default | `30` | + +--- + +### aiAssistantTools + +Tool handlers for function calls. When the AI invokes a tool, the corresponding handler is called with the parsed JSON arguments. + +| | | +| --- | --- | +| Type | `CometChatAIAssistantTools` | +| Default | `undefined` | + +--- + +### loadLastAgentConversation + +When `true`, automatically loads the most recent AI conversation on mount. + +| | | +| --- | --- | +| Type | `boolean` | +| Default | `false` | + +--- + +### showSuggestedMessages + +Whether to show suggestion pills in the empty state. + +| | | +| --- | --- | +| Type | `boolean` | +| Default | `true` | + +--- + +### suggestedMessages + +Custom suggestion texts. Overrides `user.getMetadata().suggestedMessages`. + +| | | +| --- | --- | +| Type | `string[]` | +| Default | `[]` | + +--- + +### hideChatHistory + +Hide the chat history sidebar button. + +| | | +| --- | --- | +| Type | `boolean` | +| Default | `false` | + +--- + +### hideNewChat + +Hide the "New Chat" button. + +| | | +| --- | --- | +| Type | `boolean` | +| Default | `false` | + +--- + +### showBackButton + +Show a back button in the header. + +| | | +| --- | --- | +| Type | `boolean` | +| Default | `false` | + +--- + +### showCloseButton + +Show a close button in the header. + +| | | +| --- | --- | +| Type | `boolean` | +| Default | `false` | + +--- + +### greetingView + +Custom greeting view shown in the empty state (replaces default greeting + intro text). + +| | | +| --- | --- | +| Type | `ReactNode` | +| Default | `undefined` | + +--- + +### emptyView + +Custom empty state view (replaces the entire default empty state including greeting and suggestions). + +| | | +| --- | --- | +| Type | `ReactNode` | +| Default | `undefined` | + +--- + +### parentMessageId + +Load a specific conversation thread by parent message ID. + +| | | +| --- | --- | +| Type | `number` | +| Default | `undefined` | + +--- + +### onSendButtonClick + +Called when a message is sent. + +| | | +| --- | --- | +| Type | `(message: CometChat.BaseMessage) => void` | +| Default | `undefined` | + +--- + +### onBackButtonClicked + +Called when the back button is clicked. + +| | | +| --- | --- | +| Type | `() => void` | +| Default | `undefined` | + +--- + +### onCloseButtonClicked + +Called when the close button is clicked. + +| | | +| --- | --- | +| Type | `() => void` | +| Default | `undefined` | + +--- + +### onError + +Called when an error occurs. + +| | | +| --- | --- | +| Type | `(error: unknown) => void` | +| Default | `undefined` | + +--- + +## CSS Selectors + +| Target | Selector | +| --- | --- | +| Root | `.cometchat-ai-assistant-chat` | +| Header | `.cometchat-ai-assistant-chat__header` | +| Header info | `.cometchat-ai-assistant-chat__header-info` | +| Header actions | `.cometchat-ai-assistant-chat__header-actions` | +| Header icon button | `.cometchat-ai-assistant-chat__header-icon-btn` | +| Body | `.cometchat-ai-assistant-chat__body` | +| Message list wrapper | `.cometchat-ai-assistant-chat__message-list-wrapper` | +| Empty state | `.cometchat-ai-assistant-chat__empty-state` | +| Empty state content | `.cometchat-ai-assistant-chat__empty-state-content` | +| Greeting | `.cometchat-ai-assistant-chat__empty-state-greeting` | +| Intro | `.cometchat-ai-assistant-chat__empty-state-intro` | +| Suggestions | `.cometchat-ai-assistant-chat__empty-state-suggestions` | +| Suggestion pill | `.cometchat-ai-assistant-chat__suggestion-pill` | +| Stream bubble wrapper | `.cometchat-ai-assistant-chat__stream-bubble-wrapper` | +| Composer area | `.cometchat-ai-assistant-chat__composer-area` | +| Composer streaming | `.cometchat-ai-assistant-chat__composer-area--streaming` | +| Sidebar | `.cometchat-ai-assistant-chat__sidebar` | +| Sidebar overlay | `.cometchat-ai-assistant-chat__sidebar-overlay` | +| Bubble copy footer | `.cometchat-ai-assistant-chat__bubble-footer` | +| Bubble copy button | `.cometchat-ai-assistant-chat__bubble-copy-btn` | diff --git a/ui-kit/react/components/avatar.mdx b/ui-kit/react/components/avatar.mdx new file mode 100644 index 000000000..d619a690c --- /dev/null +++ b/ui-kit/react/components/avatar.mdx @@ -0,0 +1,393 @@ +--- +title: "Avatar" +description: "A composable avatar component that displays a user or group image with initials fallback and optional online/offline status indicator." +--- + + +```json +{ + "component": "CometChatAvatar", + "package": "@cometchat/chat-uikit-react", + "import": "import { CometChatAvatar } from \"@cometchat/chat-uikit-react\";", + "cssImport": "import \"@cometchat/chat-uikit-react/css-variables.css\";", + "description": "A composable avatar component that displays a user or group image with initials fallback and optional online/offline status indicator.", + "cssRootClass": ".cometchat-avatar", + "subComponents": ["Root", "Image", "Initials", "StatusIndicator"], + "props": { + "Root": { + "name": { "type": "string", "default": "''" }, + "image": { "type": "string", "default": "''" }, + "size": { "type": "'small' | 'medium' | 'large'", "default": "'medium'" }, + "className": { "type": "string", "default": "undefined" }, + "children": { "type": "ReactNode", "default": "undefined" } + }, + "Image": { + "className": { "type": "string", "default": "undefined" } + }, + "Initials": { + "className": { "type": "string", "default": "undefined" } + }, + "StatusIndicator": { + "status": { "type": "'online' | 'offline'", "default": "undefined", "note": "Required." }, + "className": { "type": "string", "default": "undefined" } + } + }, + "types": { + "CometChatAvatarSize": "'small' | 'medium' | 'large'", + "CometChatAvatarStatus": "'online' | 'offline'", + "CometChatAvatarContextValue": { + "name": "string", + "image": "string", + "size": "CometChatAvatarSize", + "imageLoaded": "boolean", + "imageError": "boolean" + } + } +} +``` + + +## Where It Fits + +`CometChatAvatar` is a base component used throughout the UI Kit wherever a user or group needs visual representation. It appears inside `CometChatConversations`, `CometChatUsers`, `CometChatGroups`, `CometChatMessageHeader`, and `CometChatMessageBubble`. Compose the sub-components you need — render `Image` and `Initials` together for automatic fallback, add `StatusIndicator` to show presence. + +```tsx lines +import { CometChatAvatar } from "@cometchat/chat-uikit-react"; +import "@cometchat/chat-uikit-react/css-variables.css"; + +function UserProfile({ user }) { + return ( +
+ + + + + + {user.name} +
+ ); +} +``` + +## Minimal Render + +```tsx lines +import { CometChatAvatar } from "@cometchat/chat-uikit-react"; +import "@cometchat/chat-uikit-react/css-variables.css"; + +function Demo() { + return ( + + + + ); +} +``` + +Root CSS class: `.cometchat-avatar` + +## Sub-Components + +`CometChatAvatar` is a compound component with four sub-components: + +| Sub-component | Purpose | +| --- | --- | +| `Root` | Container that provides context (name, image, size, load state) to children. Renders the circular avatar wrapper. | +| `Image` | Displays the avatar image. Automatically hides when no image URL is provided or when the image fails to load. | +| `Initials` | Displays name initials as fallback text. Automatically hides when the image loads successfully. | +| `StatusIndicator` | Renders an online/offline presence dot positioned at the bottom-right corner. | + +### Root + +The outermost wrapper. Sets up the avatar context, applies size via `data-size`, and renders as a `role="img"` element with `aria-label`. + +```tsx lines + + {/* Image, Initials, StatusIndicator go here */} + +``` + +### Image + +Renders an `` tag sourced from the `image` prop on `Root`. Returns `null` when no image URL is set or when the image fails to load, allowing `Initials` to show instead. + +```tsx lines + + + + +``` + +### Initials + +Extracts initials from the `name` prop on `Root`. For multi-word names, uses the first letter of the first two words. For single-word names, uses the first two characters. Hides automatically when the image loads successfully. + +```tsx lines + + + +``` + +### StatusIndicator + +A small colored dot indicating online or offline presence. Positioned absolutely at the bottom-right of the avatar. + +```tsx lines + + + + +``` + +## Common Patterns + +### Image with initials fallback + +Render both `Image` and `Initials` together. The component automatically shows initials when the image is missing or fails to load. + +```tsx lines +import { CometChatAvatar } from "@cometchat/chat-uikit-react"; +import "@cometchat/chat-uikit-react/css-variables.css"; + +function UserAvatar({ name, image, status }) { + return ( + + + + + + ); +} +``` + +### Initials only (no image) + +Omit the `image` prop and the `Image` sub-component for a pure initials avatar. + +```tsx lines + + + +``` + +### Avatar without status indicator + +Simply don't render `StatusIndicator` — no boolean prop needed. + +```tsx lines + + + + +``` + +### Size variants side by side + +```tsx lines +import { CometChatAvatar } from "@cometchat/chat-uikit-react"; +import "@cometchat/chat-uikit-react/css-variables.css"; + +function AvatarSizes() { + return ( +
+ + + + + + + + + +
+ ); +} +``` + +## CSS Architecture + +The component uses CSS custom properties (design tokens) defined in `@cometchat/chat-uikit-react/css-variables.css`. The cascade: + +1. Global tokens set on the `.cometchat` root wrapper. +2. Component CSS (`.cometchat-avatar`) consumes these tokens via `var()`. +3. Overrides target `.cometchat-avatar` descendant selectors. + +### Key Selectors + +| Target | Selector | +| --- | --- | +| Root container | `.cometchat-avatar` | +| Image | `.cometchat-avatar__image` | +| Initials text | `.cometchat-avatar__initials` | +| Status indicator | `.cometchat-avatar__status-indicator` | +| Online modifier | `.cometchat-avatar__status-indicator[data-status="online"]` | +| Offline modifier | `.cometchat-avatar__status-indicator[data-status="offline"]` | + +### Size Modifiers + +Size is controlled via the `data-size` attribute on the root element: + +| Size | Selector | Dimensions | +| --- | --- | --- | +| Small | `.cometchat-avatar[data-size="small"]` | 28×28px | +| Medium | `.cometchat-avatar[data-size="medium"]` | 40×40px | +| Large | `.cometchat-avatar[data-size="large"]` | 48×48px | + +### Example: Brand-themed avatar + +```css lines title="App.css" +.cometchat-avatar { + background: var(--brand-primary, #6851ff); +} + +.cometchat-avatar__initials { + color: var(--brand-on-primary, #ffffff); + font-weight: 600; +} + +.cometchat-avatar__status-indicator[data-status="online"] { + background: var(--brand-success, #00c853); +} +``` + +### Customization Matrix + +| What to change | Where | Property/API | Example | +| --- | --- | --- | --- | +| Avatar size | Component props | `size` on `Root` | `` | +| Name / image | Component props | `name`, `image` on `Root` | `` | +| Show/hide status | Composition | Render or omit `StatusIndicator` | Don't render `` | +| Show/hide image | Composition | Render or omit `Image` | Don't render `` | +| Background color | Global CSS | `.cometchat-avatar` | `background: #6851ff;` | +| Initials font | Global CSS | `.cometchat-avatar__initials` | `font-weight: 600;` | +| Status dot color | Global CSS | `.cometchat-avatar__status-indicator[data-status]` | `background: #00c853;` | +| Border radius | Global CSS | `--cometchat-radius-max` | `--cometchat-radius-max: 8px;` | + +## Props + +All props are optional unless noted otherwise. + +--- + +### CometChatAvatar.Root + +#### name + +Name used for generating initials and as the `aria-label` on the root element. + +| | | +| --- | --- | +| Type | `string` | +| Default | `''` | + +--- + +#### image + +URL of the avatar image. When provided, `Image` sub-component renders an `` tag. When the URL fails to load, `Initials` automatically takes over. + +| | | +| --- | --- | +| Type | `string` | +| Default | `''` | + +--- + +#### size + +Controls the avatar dimensions. `small` is 28px, `medium` is 40px, `large` is 48px. + +| | | +| --- | --- | +| Type | `'small' \| 'medium' \| 'large'` | +| Default | `'medium'` | + +--- + +#### className + +Custom CSS class appended to the root container. + +| | | +| --- | --- | +| Type | `string` | +| Default | `undefined` | + +--- + +#### children + +Sub-components to render inside the avatar. Typically `Image`, `Initials`, and optionally `StatusIndicator`. + +| | | +| --- | --- | +| Type | `ReactNode` | +| Default | `undefined` | + +--- + +### CometChatAvatar.Image + +#### className + +Custom CSS class appended to the `` element. + +| | | +| --- | --- | +| Type | `string` | +| Default | `undefined` | + +--- + +### CometChatAvatar.Initials + +#### className + +Custom CSS class appended to the initials `` element. + +| | | +| --- | --- | +| Type | `string` | +| Default | `undefined` | + +--- + +### CometChatAvatar.StatusIndicator + +#### status + +The presence status to display. Renders a green dot for `online` and a gray dot for `offline`. + +| | | +| --- | --- | +| Type | `'online' \| 'offline'` | +| Default | `undefined` | + +**Required.** + +--- + +#### className + +Custom CSS class appended to the status indicator `` element. + +| | | +| --- | --- | +| Type | `string` | +| Default | `undefined` | + +--- + +## CSS Selectors + +| Target | Selector | +| --- | --- | +| Root | `.cometchat-avatar` | +| Root (small) | `.cometchat-avatar[data-size="small"]` | +| Root (medium) | `.cometchat-avatar[data-size="medium"]` | +| Root (large) | `.cometchat-avatar[data-size="large"]` | +| Image | `.cometchat-avatar__image` | +| Initials | `.cometchat-avatar__initials` | +| Status indicator | `.cometchat-avatar__status-indicator` | +| Status (online) | `.cometchat-avatar__status-indicator[data-status="online"]` | +| Status (offline) | `.cometchat-avatar__status-indicator[data-status="offline"]` | diff --git a/ui-kit/react/components/button.mdx b/ui-kit/react/components/button.mdx new file mode 100644 index 000000000..6180fe952 --- /dev/null +++ b/ui-kit/react/components/button.mdx @@ -0,0 +1,317 @@ +--- +title: "Button" +description: "Base clickable element supporting text, icon, or both, with keyboard activation and accessible labeling for icon-only usage." +--- + + +```json +{ + "component": "CometChatButton", + "package": "@cometchat/chat-uikit-react", + "import": "import { CometChatButton } from \"@cometchat/chat-uikit-react\";", + "cssImport": "import \"@cometchat/chat-uikit-react/css-variables.css\";", + "description": "Base clickable element supporting text, icon, or both, with keyboard activation and accessible labeling for icon-only usage.", + "cssRootClass": ".cometchat-button", + "primaryOutput": { + "prop": "onClick", + "type": "(event: React.MouseEvent) => void" + }, + "props": { + "data": { + "text": { "type": "string", "default": "undefined", "note": "Button label text. At least one of text or iconURL is required." }, + "iconURL": { "type": "string", "default": "undefined", "note": "Icon image source. At least one of text or iconURL is required." }, + "disabled": { "type": "boolean", "default": "false" }, + "variant": { "type": "\"primary\" | \"secondary\" | \"ghost\"", "default": "\"primary\"" } + }, + "callbacks": { + "onClick": "(event: React.MouseEvent) => void" + } + }, + "events": [], + "sdkListeners": [], + "types": {} +} +``` + + +## Where It Fits + +`CometChatButton` is a base element used throughout the UI Kit for clickable actions — send buttons, attachment triggers, cancel actions, toolbar icons, and dialog confirmations. It renders as a native ` + + +
+ ); +} +``` + +## Accessibility + +- List container: `role="listbox"` with `aria-label="Group members list"` +- Member items: `role="option"` with `aria-selected` and descriptive `aria-label` (includes name, role, and status) +- Role badges: `aria-hidden="true"` (info is in the item's `aria-label`) +- Action menu trigger: accessible via keyboard (Tab to reach, Enter to open) +- Loading state: `aria-busy="true"`, `aria-live="polite"` +- Empty/Error states: `role="status"` / `role="alert"` +- Keyboard: `Tab` to focus, `Enter`/`Space` to select, `Escape` to close menus +- All interactive elements have `:focus-visible` styles + +## CSS Customization + +The component uses CSS custom properties for theming: + +```css +/* Override in your app */ +:root { + --cometchat-primary-color: #6851d6; + --cometchat-background-color-01: #ffffff; + --cometchat-text-color-primary: #141414; + --cometchat-text-color-secondary: #727272; + --cometchat-success-color: #09c26f; + --cometchat-error-color: #f44336; +} +``` + +## Real-Time Updates + +The component automatically handles: +- **Member joined** — adds new member to the list +- **Member left** — removes member from the list +- **Member banned** — removes member from the list +- **Member kicked** — removes member from the list +- **Scope changed** — updates the member's role badge +- **User online** — shows online status indicator +- **User offline** — shows offline status indicator +- **Connection recovery** — re-fetches members on network reconnect +- **Selection persistence** — selections persist across search operations diff --git a/ui-kit/react/components/cometchat-groups.mdx b/ui-kit/react/components/cometchat-groups.mdx new file mode 100644 index 000000000..042427ad8 --- /dev/null +++ b/ui-kit/react/components/cometchat-groups.mdx @@ -0,0 +1,338 @@ +--- +title: CometChatGroups +description: A scrollable, searchable list of groups with real-time group events, group type indicators, selection modes, and infinite scroll pagination. +--- + +## Overview + +`CometChatGroups` displays a real-time list of groups in your CometChat app. It supports infinite scroll pagination, search with debounce, group type indicators (public/private/password-protected), single/multiple selection modes with shift-click range selection, and group mutations (create, join, leave, delete). + +It offers **two usage modes**: +- **Flat API** — pass convenience props directly to `` for quick customization +- **Compound API** — use `` with sub-components for full layout control + +## Import + +```tsx +import { CometChatGroups } from '@cometchat/chat-uikit-react'; +``` + +## Quick Start + +### Flat API (Simple) + +The flat API is the simplest way to render a group list. Pass props directly to ``: + +```tsx + console.log('Selected:', group.getName())} + subtitleView={(group) => {group.getMembersCount()} members} +/> +``` + +### Compound API (Advanced) + +Use the compound API for full control over layout and rendering. Place only the sub-components you need inside ``: + +```tsx + + + + + + + + +``` + + +State sub-components (`LoadingState`, `ErrorState`, `EmptyState`) are **self-managing** — they read `fetchState` from context and automatically show/hide themselves. You don't need conditional rendering. + + +## Sub-Components + +| Component | Description | +|---|---| +| `CometChatGroups.Root` | Provider + default layout. Wraps children with context. | +| `CometChatGroups.Header` | Header with title text (defaults to "Groups"). | +| `CometChatGroups.SearchBar` | Debounced search input (300ms). | +| `CometChatGroups.List` | Group list with infinite scroll. Self-manages visibility based on fetch state. | +| `CometChatGroups.Item` | Individual group item (avatar, name, member count, type badge, selection control). | +| `CometChatGroups.EmptyState` | Self-managing — only renders when `fetchState === 'empty'`. | +| `CometChatGroups.ErrorState` | Self-managing — only renders when `fetchState === 'error'`. | +| `CometChatGroups.LoadingState` | Self-managing — only renders when `fetchState === 'loading'`. | + +## Props + +### Flat API (``) + +All Root props below, plus these convenience view props: + +| Prop | Type | Description | +|---|---|---| +| `leadingView` | `(group: CometChat.Group) => ReactNode` | Custom leading view per item (replaces avatar). | +| `titleView` | `(group: CometChat.Group) => ReactNode` | Custom title view per item. | +| `subtitleView` | `(group: CometChat.Group) => ReactNode` | Custom subtitle view per item. | +| `trailingView` | `(group: CometChat.Group) => ReactNode` | Custom trailing view per item. | +| `itemView` | `(group: CometChat.Group) => ReactNode` | Fully custom item (overrides all above). | +| `headerView` | `ReactNode` | Custom header (replaces default). | +| `loadingView` | `ReactNode` | Custom loading content. | +| `errorView` | `ReactNode` | Custom error content. | +| `emptyView` | `ReactNode` | Custom empty content. | + +### CometChatGroups.Root + +| Prop | Type | Default | Description | +|---|---|---|---| +| `requestBuilder` | `CometChat.GroupsRequestBuilder` | limit 30 | Custom request builder for fetching groups. | +| `searchRequestBuilder` | `CometChat.GroupsRequestBuilder` | — | Custom request builder for search queries. | +| `searchKeyword` | `string` | `''` | Initial search keyword. | +| `hideGroupType` | `boolean` | `false` | Whether to hide the group type badge (public/private/password). | +| `selectionMode` | `'none' \| 'single' \| 'multiple'` | `'none'` | Selection mode. | +| `activeGroup` | `CometChat.Group` | — | Group to highlight as active. | +| `options` | `(group: CometChat.Group) => CometChatGroupOption[]` | — | Context menu options per group. | +| `onItemClick` | `(group: CometChat.Group) => void` | — | Callback when a group is clicked. Used for sibling component communication. | +| `onSelect` | `(group: CometChat.Group, selected: boolean) => void` | — | Callback when selection changes. | +| `onError` | `(error: unknown) => void` | — | Callback when an error occurs. | +| `onEmpty` | `() => void` | — | Callback when the list is empty. | +| `showScrollbar` | `boolean` | `false` | Show the native scrollbar on the list. | +| `children` | `ReactNode` | — | Custom layout. If omitted, renders default. | + +### CometChatGroups.Header + +| Prop | Type | Default | Description | +|---|---|---|---| +| `title` | `string` | `'Groups'` | Custom title text. | +| `children` | `ReactNode` | — | Custom header content (replaces default). | + +### CometChatGroups.SearchBar + +| Prop | Type | Default | Description | +|---|---|---|---| +| `placeholder` | `string` | `'Search groups'` | Placeholder text for the search input. | + +### CometChatGroups.List + +| Prop | Type | Default | Description | +|---|---|---|---| +| `itemView` | `(group: CometChat.Group) => ReactNode` | — | Custom render function for each group item. | + +### CometChatGroups.Item + +| Prop | Type | Default | Description | +|---|---|---|---| +| `group` | `CometChat.Group` | required | The group to render. | +| `isActive` | `boolean` | — | Override active state. | +| `leadingView` | `ReactNode` | — | Custom leading view (replaces avatar). | +| `titleView` | `ReactNode` | — | Custom title view. | +| `subtitleView` | `ReactNode` | — | Custom subtitle view (replaces member count). | +| `trailingView` | `ReactNode` | — | Custom trailing view (replaces selection control). | + +### CometChatGroups.EmptyState + +| Prop | Type | Default | Description | +|---|---|---|---| +| `children` | `ReactNode` | — | Custom empty state content (replaces default). | + +### CometChatGroups.ErrorState + +| Prop | Type | Default | Description | +|---|---|---|---| +| `children` | `ReactNode` | — | Custom error state content (replaces default). | + +### CometChatGroups.LoadingState + +| Prop | Type | Default | Description | +|---|---|---|---| +| `children` | `ReactNode` | — | Custom loading state content (replaces default shimmer). | + +## Sibling Communication with onItemClick + +The `onItemClick` callback enables communication between sibling components. The parent component owns the shared state and passes it down: + +```tsx +import { CometChatGroups } from '@cometchat/chat-uikit-react'; +import { CometChatMessageList } from '@cometchat/chat-uikit-react'; +import { useState } from 'react'; +import { CometChat } from '@cometchat/chat-sdk-javascript'; + +function ChatApp() { + const [activeGroup, setActiveGroup] = useState(null); + + return ( +
+ + + {activeGroup && ( + + )} +
+ ); +} +``` + +## Custom Request Builder + +Use `requestBuilder` to customize the SDK query for fetching groups: + +```tsx +import { CometChat } from '@cometchat/chat-sdk-javascript'; + +const builder = new CometChat.GroupsRequestBuilder() + .setLimit(50) + .joinedOnly(true); + + +``` + +You can also provide a separate `searchRequestBuilder` for search queries: + +```tsx +const searchBuilder = new CometChat.GroupsRequestBuilder() + .setLimit(30) + .setSearchKeyword(''); // keyword will be set dynamically + + +``` + +## Group Types + +Each group displays a type badge at the bottom-right of the avatar (unless `hideGroupType` is set to `true`): + +| Type | Badge | Description | +|---|---|---| +| Public | No badge | Open group, anyone can join. | +| Private | Orange circle + shield icon | Invite-only group. | +| Password | Green circle + lock icon | Requires password to join. | + +```tsx +// Hide the group type badge + +``` + +## Selection Modes + +### None (default) +No selection controls are shown. Clicking a group triggers `onItemClick`. + +### Single +Radio buttons appear in the trailing view. Only one group can be selected at a time. + +### Multiple +Checkboxes appear in the trailing view. Multiple groups can be selected. Supports **shift-click range selection**. + +```tsx + { + console.log(group.getName(), selected ? 'selected' : 'deselected'); + }} +> + + + + +``` + +## Group Mutations + +The context exposes mutation methods for group operations: + +```tsx +import { useCometChatGroupsContext } from '@cometchat/chat-uikit-react'; + +function GroupActions() { + const { createGroup, joinGroup, leaveGroup, deleteGroup } = useCometChatGroupsContext(); + + const handleJoin = async (guid: string) => { + await joinGroup(guid, 'public'); + }; + + const handleJoinPassword = async (guid: string, password: string) => { + await joinGroup(guid, 'password', password); + }; + + const handleLeave = async (guid: string) => { + await leaveGroup(guid); + }; + + const handleDelete = async (guid: string) => { + await deleteGroup(guid); + }; + + return null; +} +``` + +## Context Hook + +Access the groups context from any child component inside `CometChatGroups.Root`: + +```tsx +import { useCometChatGroupsContext } from '@cometchat/chat-uikit-react'; + +function CustomGroupCount() { + const { groups, fetchState } = useCometChatGroupsContext(); + if (fetchState !== 'loaded') return null; + return {groups.length} groups; +} +``` + +The context provides: + +| Property | Type | Description | +|---|---|---| +| `groups` | `CometChat.Group[]` | List of fetched groups. | +| `fetchState` | `'idle' \| 'loading' \| 'loaded' \| 'error' \| 'empty'` | Current fetch lifecycle state. | +| `hasMore` | `boolean` | Whether more pages are available. | +| `error` | `string \| null` | Error message (if fetchState is 'error'). | +| `selectedGroupIds` | `string[]` | GUIDs of selected groups. | +| `searchText` | `string` | Current search text. | +| `fetchNext` | `() => Promise` | Fetch next page of groups. | +| `setSearchText` | `(text: string) => void` | Set search text (triggers re-fetch). | +| `selectGroup` | `(group: CometChat.Group) => void` | Select a group. | +| `deselectGroup` | `(groupId: string) => void` | Deselect a group by GUID. | +| `clearSelection` | `() => void` | Clear all selections. | +| `createGroup` | `(group: CometChat.Group) => Promise` | Create a new group. | +| `joinGroup` | `(guid, groupType, password?) => Promise` | Join a group. | +| `leaveGroup` | `(guid: string) => Promise` | Leave a group. | +| `deleteGroup` | `(guid: string) => Promise` | Delete a group. | + +## Accessibility + +- List container: `role="listbox"` with `aria-label="Groups list"` +- Group items: `role="option"` with `aria-selected` +- Group type badges: `aria-label` describing the type (e.g., "Private group", "Password protected group") +- Loading state: `aria-busy="true"` +- Empty/Error states: `role="status"` +- Keyboard: `Tab` to focus, `ArrowUp`/`ArrowDown` to navigate, `Enter`/`Space` to select, `Escape` to clear search +- All icon-only buttons have `aria-label` + +## CSS Customization + +The component uses CSS custom properties for theming: + +```css +:root { + --cometchat-primary-color: #6851d6; + --cometchat-background-color-01: #ffffff; + --cometchat-text-color-primary: #141414; + --cometchat-text-color-secondary: #727272; + --cometchat-success-color: #09c26f; + --cometchat-warning-color: #ffab00; +} +``` + +## Real-Time Updates + +The component automatically handles: +- **Member joined** — updates member count +- **Member left** — updates member count; removes group if logged-in user left +- **Member banned/kicked** — updates member count; removes group if logged-in user was banned/kicked +- **Scope changed** — updates group in list +- **Group deleted** — removes group from list +- **Connection recovery** — re-fetches groups on network reconnect +- **Selection persistence** — selections persist across search operations diff --git a/ui-kit/react/components/cometchat-users.mdx b/ui-kit/react/components/cometchat-users.mdx new file mode 100644 index 000000000..07c016db6 --- /dev/null +++ b/ui-kit/react/components/cometchat-users.mdx @@ -0,0 +1,831 @@ +--- +title: "Users" +description: "A scrollable, searchable list of users with real-time status updates, selection modes, and infinite scroll pagination." +--- + + +```json +{ + "component": "CometChatUsers", + "package": "@cometchat/chat-uikit-react", + "import": "import { CometChatUsers } from \"@cometchat/chat-uikit-react\";", + "cssImport": "import \"@cometchat/chat-uikit-react/css-variables.css\";", + "description": "A scrollable, searchable list of users with real-time status updates, selection modes, and infinite scroll pagination.", + "cssRootClass": ".cometchat-users", + "primaryOutput": { + "prop": "onItemClick", + "type": "(user: CometChat.User) => void" + }, + "subComponents": [ + "CometChatUsers.Root", + "CometChatUsers.List", + "CometChatUsers.Item", + "CometChatUsers.Header", + "CometChatUsers.SearchBar", + "CometChatUsers.SectionHeader", + "CometChatUsers.EmptyState", + "CometChatUsers.ErrorState", + "CometChatUsers.LoadingState", + "CometChatUsers.SelectedPreview" + ], + "props": { + "data": { + "requestBuilder": { "type": "CometChat.UsersRequestBuilder", "default": "limit 30" }, + "searchRequestBuilder": { "type": "CometChat.UsersRequestBuilder", "default": "undefined" }, + "searchKeyword": { "type": "string", "default": "\"\"" }, + "activeUser": { "type": "CometChat.User", "default": "undefined" }, + "sectionHeaderKey": { "type": "keyof CometChat.User", "default": "\"getName\"" } + }, + "callbacks": { + "onItemClick": { "type": "(user: CometChat.User) => void", "default": "undefined" }, + "onSelect": { "type": "(user: CometChat.User, selected: boolean) => void", "default": "undefined" }, + "onError": { "type": "(error: unknown) => void", "default": "undefined" }, + "onEmpty": { "type": "() => void", "default": "undefined" } + }, + "visibility": { + "hideUserStatus": { "type": "boolean", "default": "false" }, + "showScrollbar": { "type": "boolean", "default": "false" } + }, + "behavior": { + "selectionMode": { "type": "'none' | 'single' | 'multiple'", "default": "'none'" }, + "options": { "type": "(user: CometChat.User) => CometChatUserOption[]", "default": "undefined" } + }, + "viewSlots": { + "leadingView": { "type": "(user: CometChat.User) => ReactNode", "default": "undefined" }, + "titleView": { "type": "(user: CometChat.User) => ReactNode", "default": "undefined" }, + "subtitleView": { "type": "(user: CometChat.User) => ReactNode", "default": "undefined" }, + "trailingView": { "type": "(user: CometChat.User) => ReactNode", "default": "undefined" }, + "itemView": { "type": "(user: CometChat.User) => ReactNode", "default": "undefined" }, + "headerView": { "type": "ReactNode", "default": "undefined" }, + "loadingView": { "type": "ReactNode", "default": "undefined" }, + "errorView": { "type": "ReactNode", "default": "undefined" }, + "emptyView": { "type": "ReactNode", "default": "undefined" } + } + }, + "events": [], + "sdkListeners": ["onUserOnline", "onUserOffline", "onConnected"], + "types": { + "CometChatUsersSelectionMode": "'none' | 'single' | 'multiple'", + "CometChatUserOption": "{ id: string; title: string; iconURL?: string; onClick: (user: CometChat.User) => void }", + "CometChatFetchState": "'idle' | 'loading' | 'loaded' | 'error' | 'empty'" + } +} +``` + + +## Where It Fits + +`CometChatUsers` is a feature component that fetches and displays a paginated list of CometChat users. Wire it to `CometChatMessageList` via the `onItemClick` callback to build a one-to-one chat interface — selecting a user loads the conversation in the message pane. + +```tsx lines +import { useState } from "react"; +import { CometChat } from "@cometchat/chat-sdk-javascript"; +import { CometChatUsers, CometChatMessageList } from "@cometchat/chat-uikit-react"; +import "@cometchat/chat-uikit-react/css-variables.css"; + +function ChatApp() { + const [selectedUser, setSelectedUser] = useState(null); + + return ( +
+ + {selectedUser && } +
+ ); +} +``` + +## Minimal Render + +```tsx lines +import { CometChatUsers } from "@cometchat/chat-uikit-react"; +import "@cometchat/chat-uikit-react/css-variables.css"; + +function Demo() { + return ; +} +``` + +Root CSS class: `.cometchat-users` + +## Usage Modes + +CometChatUsers supports two modes: a **Flat API** for quick setup and a **Compound API** for full layout control. + +### Flat API + +Pass all props directly to ``. The component renders its default layout (header, search bar, list, state indicators) with your customizations applied: + +```tsx lines +import { CometChatUsers } from "@cometchat/chat-uikit-react"; +import "@cometchat/chat-uikit-react/css-variables.css"; + +function Demo() { + return ( + console.log("Selected:", user.getName())} + subtitleView={(user) => {user.getStatus()}} + trailingView={(user) => } + /> + ); +} +``` + +### Compound API + +Use `CometChatUsers.Root` with sub-components for full control over layout and which pieces render. Omit a sub-component to hide it — no boolean props needed: + +```tsx lines +import { CometChatUsers } from "@cometchat/chat-uikit-react"; +import "@cometchat/chat-uikit-react/css-variables.css"; + +function Demo() { + return ( + + + + + + + + + + ); +} +``` + + +State sub-components (`LoadingState`, `ErrorState`, `EmptyState`) are **self-managing** — they read `fetchState` from context and automatically show/hide themselves. Place them all in the tree without conditional rendering. + + +## Sub-Components + +| Component | Description | +|---|---| +| `CometChatUsers.Root` | Calls the data hook, provides context, renders default layout when no children passed. | +| `CometChatUsers.Header` | Header with title text. Accepts optional `title` and `children` props. | +| `CometChatUsers.SearchBar` | Debounced search input (300ms). Accepts optional `placeholder` prop. | +| `CometChatUsers.List` | User list with infinite scroll. Only renders when users are available. | +| `CometChatUsers.Item` | Individual user row (avatar, name, status, selection control). | +| `CometChatUsers.SectionHeader` | Alphabetical section divider (e.g., "A", "B"). | +| `CometChatUsers.EmptyState` | Renders when `fetchState === 'empty'`. Pass `children` for custom content. | +| `CometChatUsers.ErrorState` | Renders when `fetchState === 'error'`. Pass `children` for custom content. | +| `CometChatUsers.LoadingState` | Renders when `fetchState === 'loading'`. Pass `children` for custom shimmer. | +| `CometChatUsers.SelectedPreview` | Chips showing selected users (visible in multiple selection mode). | + +## Filtering Users + +Pass a `CometChat.UsersRequestBuilder` to `requestBuilder`. Pass the builder instance — not the result of `.build()`. + +```tsx lines +import { CometChat } from "@cometchat/chat-sdk-javascript"; +import { CometChatUsers } from "@cometchat/chat-uikit-react"; +import "@cometchat/chat-uikit-react/css-variables.css"; + +const builder = new CometChat.UsersRequestBuilder() + .setLimit(50) + .setRoles(["admin", "moderator"]); + +function AdminUsers() { + return ; +} +``` + +### Filter Recipes + +| Recipe | Code | +|---|---| +| Limit to 50 users per page | `new CometChat.UsersRequestBuilder().setLimit(50)` | +| Only friends | `new CometChat.UsersRequestBuilder().friendsOnly(true)` | +| Filter by role | `new CometChat.UsersRequestBuilder().setRoles(["admin"])` | +| Filter by status | `new CometChat.UsersRequestBuilder().setStatus("online")` | +| Search by keyword | `new CometChat.UsersRequestBuilder().setSearchKeyword("john")` | + +### Search Request Builder + +Use `searchRequestBuilder` to customize the search behavior independently from the initial fetch: + +```tsx lines +import { CometChat } from "@cometchat/chat-sdk-javascript"; +import { CometChatUsers } from "@cometchat/chat-uikit-react"; +import "@cometchat/chat-uikit-react/css-variables.css"; + +const searchBuilder = new CometChat.UsersRequestBuilder() + .setLimit(20) + .setRoles(["admin"]); + +function Demo() { + return ; +} +``` + +## Actions and Events + +### Callback Props + +#### onItemClick + +Fires when a user item is clicked (in `selectionMode: 'none'`). Use this to drive navigation or load a conversation: + +```tsx lines +import { CometChat } from "@cometchat/chat-sdk-javascript"; +import { CometChatUsers } from "@cometchat/chat-uikit-react"; +import "@cometchat/chat-uikit-react/css-variables.css"; + +function Demo() { + const handleUserClick = (user: CometChat.User) => { + console.log("Navigate to chat with:", user.getName()); + }; + + return ; +} +``` + +#### onSelect + +Fires when a user is selected or deselected (in `single` or `multiple` selection mode): + +```tsx lines +import { CometChat } from "@cometchat/chat-sdk-javascript"; +import { CometChatUsers } from "@cometchat/chat-uikit-react"; +import "@cometchat/chat-uikit-react/css-variables.css"; + +function Demo() { + const handleSelect = (user: CometChat.User, selected: boolean) => { + console.log(user.getName(), selected ? "selected" : "deselected"); + }; + + return ; +} +``` + +#### onError + +Fires when an SDK fetch or listener error occurs. Use for logging or toast notifications: + +```tsx lines +import { CometChatUsers } from "@cometchat/chat-uikit-react"; +import "@cometchat/chat-uikit-react/css-variables.css"; + +function Demo() { + return ( + console.error("Users fetch failed:", error)} + /> + ); +} +``` + +#### onEmpty + +Fires when the initial fetch returns zero users: + +```tsx lines +import { CometChatUsers } from "@cometchat/chat-uikit-react"; +import "@cometchat/chat-uikit-react/css-variables.css"; + +function Demo() { + return ( + console.log("No users found")} /> + ); +} +``` + +### SDK Events (Real-Time, Automatic) + +CometChatUsers automatically subscribes to SDK listeners for real-time updates. No manual setup required. + +| SDK Listener | Internal Behavior | +|---|---| +| `onUserOnline` | Updates user status indicator to online | +| `onUserOffline` | Updates user status indicator to offline | +| `onConnected` | Re-initializes the request builder and re-fetches from the beginning | + + +In React 18 StrictMode, `useEffect` runs twice on mount in development. The component handles this gracefully by using unique listener IDs per instance and cleaning up on unmount. + + +## Custom View Slots + +| Slot | Signature | Replaces | +|---|---|---| +| `itemView` | `(user: CometChat.User) => ReactNode` | Entire list item row | +| `leadingView` | `(user: CometChat.User) => ReactNode` | Avatar | +| `titleView` | `(user: CometChat.User) => ReactNode` | User name | +| `subtitleView` | `(user: CometChat.User) => ReactNode` | Status text | +| `trailingView` | `(user: CometChat.User) => ReactNode` | Selection control / trailing content | +| `headerView` | `ReactNode` | Default header | +| `loadingView` | `ReactNode` | Default shimmer | +| `errorView` | `ReactNode` | Default error message | +| `emptyView` | `ReactNode` | Default empty message | + +### subtitleView + +Add custom subtitle content below the user name: + +```tsx lines +import { CometChat } from "@cometchat/chat-sdk-javascript"; +import { CometChatUsers } from "@cometchat/chat-uikit-react"; +import "@cometchat/chat-uikit-react/css-variables.css"; + +function Demo() { + return ( + ( + + {user.getStatus()} + + )} + /> + ); +} +``` + +### itemView + +Replace the entire item row with a custom component: + +```tsx lines +import { CometChat } from "@cometchat/chat-sdk-javascript"; +import { CometChatUsers } from "@cometchat/chat-uikit-react"; +import "@cometchat/chat-uikit-react/css-variables.css"; + +function Demo() { + return ( + ( +
+ {user.getName()} +
+ {user.getName()} +

{user.getRole()}

+
+
+ )} + /> + ); +} +``` + +### Custom States (Compound API) + +With the compound API, pass custom content as children to state sub-components: + +```tsx lines +import { CometChatUsers } from "@cometchat/chat-uikit-react"; +import "@cometchat/chat-uikit-react/css-variables.css"; + +function Demo() { + return ( + + + + +
Loading users...
+
+ +
+ Something went wrong. Please try again. +
+
+ +
No users found.
+
+ +
+ ); +} +``` + +## Common Patterns + +### Sibling Communication (Users → Messages) + +Drive a message list from user selection using parent state and the `onItemClick` callback: + +```tsx lines +import { useState } from "react"; +import { CometChat } from "@cometchat/chat-sdk-javascript"; +import { CometChatUsers, CometChatMessageList } from "@cometchat/chat-uikit-react"; +import "@cometchat/chat-uikit-react/css-variables.css"; + +function ChatApp() { + const [activeUser, setActiveUser] = useState(null); + + return ( +
+
+ +
+
+ {activeUser && } +
+
+ ); +} +``` + +### Multiple Selection with Submit + +Collect selected users and submit them (e.g., for creating a group): + +```tsx lines +import { useState } from "react"; +import { CometChat } from "@cometchat/chat-sdk-javascript"; +import { CometChatUsers, useCometChatUsersContext } from "@cometchat/chat-uikit-react"; +import "@cometchat/chat-uikit-react/css-variables.css"; + +function SubmitButton() { + const { selectedUsersMap } = useCometChatUsersContext(); + const selectedUsers = Array.from(selectedUsersMap.values()); + + return ( + + ); +} + +function GroupCreator() { + return ( + + + + + + + + + + + ); +} +``` + +### Context Hook + +Access user list state from any child rendered inside `CometChatUsers.Root`: + +```tsx lines +import { useCometChatUsersContext } from "@cometchat/chat-uikit-react"; + +function UserCount() { + const { users, fetchState } = useCometChatUsersContext(); + + if (fetchState !== "loaded") return null; + return {users.length} users loaded; +} +``` + +## CSS Architecture + +The component uses CSS custom properties (design tokens) defined in `@cometchat/chat-uikit-react/css-variables.css`. The cascade: + +1. Global tokens set on the `.cometchat` root wrapper. +2. Component CSS (`.cometchat-users`) consumes these tokens via `var()`. +3. Overrides target `.cometchat-users` descendant selectors. + +### Key Selectors + +| Target | Selector | +|---|---| +| Root container | `.cometchat-users` | +| Header | `.cometchat-users__header` | +| Search bar | `.cometchat-users__search-bar` | +| List container | `.cometchat-users__list` | +| User item | `.cometchat-users__item` | +| Section header | `.cometchat-users__section-header` | +| Empty state | `.cometchat-users__empty-state` | +| Error state | `.cometchat-users__error-state` | +| Loading state | `.cometchat-users__loading-state` | +| Selected preview | `.cometchat-users__selected-preview` | + +### Example: Brand-themed users list + +```css lines title="App.css" +.cometchat-users { + --cometchat-primary-color: #6851d6; + --cometchat-background-color-01: #fafafa; + --cometchat-text-color-primary: #1a1a1a; + --cometchat-text-color-secondary: #666666; + --cometchat-success-color: #22c55e; +} + +.cometchat-users__item:hover { + background-color: #f0ecfb; +} +``` + +### Customization Matrix + +| What to change | Where | Property/API | Example | +|---|---|---|---| +| Override behavior | Component props | `onItemClick`, `onSelect`, `onError` callbacks | `onItemClick={(user) => navigate(user)}` | +| Filter data | Component props | `requestBuilder` | Builder with `.setRoles(["admin"])` | +| Toggle UI elements | Compound API | Omit sub-component | Remove `` to hide search | +| Replace UI sections | Flat API props | `headerView`, `emptyView`, `loadingView` | `emptyView={}` | +| Change visual styling | Global CSS | `.cometchat-users` selectors | See CSS example above | + +## Props + +All props are optional unless noted otherwise. + +--- + +### requestBuilder + +Custom request builder for fetching users. Controls pagination, filtering, and sorting. + +| | | +|---|---| +| Type | `CometChat.UsersRequestBuilder` | +| Default | Internal builder with limit 30 | + +--- + +### searchRequestBuilder + +Custom request builder used specifically for search queries. When the user types in the search bar, this builder is used instead of `requestBuilder`. + +| | | +|---|---| +| Type | `CometChat.UsersRequestBuilder` | +| Default | `undefined` | + +--- + +### searchKeyword + +Initial search keyword to pre-filter the user list on mount. + +| | | +|---|---| +| Type | `string` | +| Default | `""` | + +--- + +### hideUserStatus + +Hide the online/offline status indicator dot on user items. + +| | | +|---|---| +| Type | `boolean` | +| Default | `false` | + +--- + +### selectionMode + +Controls selection behavior and the UI controls shown on each item. + +| | | +|---|---| +| Type | `'none' \| 'single' \| 'multiple'` | +| Default | `'none'` | + +- `'none'`: No selection controls. Clicking triggers `onItemClick`. +- `'single'`: Radio buttons appear. One user selectable at a time. +- `'multiple'`: Checkboxes appear. Supports shift-click range selection. + +--- + +### activeUser + +The currently highlighted user. The matching item receives an active visual state. + +| | | +|---|---| +| Type | `CometChat.User` | +| Default | `undefined` | + +--- + +### sectionHeaderKey + +The property used to extract alphabetical section headers from each user object. + +| | | +|---|---| +| Type | `keyof CometChat.User` | +| Default | `'getName'` | + +--- + +### options + +Function that returns context menu options for each user. Options appear on hover/long-press. + +| | | +|---|---| +| Type | `(user: CometChat.User) => CometChatUserOption[]` | +| Default | `undefined` | + +```typescript +interface CometChatUserOption { + id: string; + title: string; + iconURL?: string; + onClick: (user: CometChat.User) => void; +} +``` + +--- + +### onItemClick + +Callback when a user item is clicked (only fires in `selectionMode: 'none'`). Use for sibling component communication. + +| | | +|---|---| +| Type | `(user: CometChat.User) => void` | +| Default | `undefined` | + +--- + +### onSelect + +Callback when a user is selected or deselected (fires in `single` or `multiple` mode). + +| | | +|---|---| +| Type | `(user: CometChat.User, selected: boolean) => void` | +| Default | `undefined` | + +--- + +### onError + +Callback when an error occurs during fetch or real-time listener operations. + +| | | +|---|---| +| Type | `(error: unknown) => void` | +| Default | `undefined` | + +--- + +### onEmpty + +Callback when the initial fetch returns zero users. + +| | | +|---|---| +| Type | `() => void` | +| Default | `undefined` | + +--- + +### showScrollbar + +Whether to show the native scrollbar on the list. When `false`, the scrollbar is hidden via CSS but scrolling still works. + +| | | +|---|---| +| Type | `boolean` | +| Default | `false` | + +--- + +### leadingView + +Custom leading view per user item. Replaces the default avatar. + +| | | +|---|---| +| Type | `(user: CometChat.User) => ReactNode` | +| Default | `undefined` | + +--- + +### titleView + +Custom title view per user item. Replaces the user name. + +| | | +|---|---| +| Type | `(user: CometChat.User) => ReactNode` | +| Default | `undefined` | + +--- + +### subtitleView + +Custom subtitle view per user item. Renders below the title. + +| | | +|---|---| +| Type | `(user: CometChat.User) => ReactNode` | +| Default | `undefined` | + +--- + +### trailingView + +Custom trailing view per user item. Replaces the selection control in selection modes. + +| | | +|---|---| +| Type | `(user: CometChat.User) => ReactNode` | +| Default | `undefined` | + +--- + +### itemView + +Fully custom item renderer. Overrides `leadingView`, `titleView`, `subtitleView`, and `trailingView`. + +| | | +|---|---| +| Type | `(user: CometChat.User) => ReactNode` | +| Default | `undefined` | + +--- + +### headerView + +Custom header content. Replaces the default header entirely. + +| | | +|---|---| +| Type | `ReactNode` | +| Default | `undefined` | + +--- + +### loadingView + +Custom loading state content. Replaces the default shimmer animation. + +| | | +|---|---| +| Type | `ReactNode` | +| Default | `undefined` | + +--- + +### errorView + +Custom error state content. Replaces the default error message. + +| | | +|---|---| +| Type | `ReactNode` | +| Default | `undefined` | + +--- + +### emptyView + +Custom empty state content. Replaces the default "no users" message. + +| | | +|---|---| +| Type | `ReactNode` | +| Default | `undefined` | + +## CSS Selectors + +| Target | Selector | +|---|---| +| Root | `.cometchat-users` | +| Header | `.cometchat-users__header` | +| Header title | `.cometchat-users__header-title` | +| Search bar | `.cometchat-users__search-bar` | +| List | `.cometchat-users__list` | +| Item | `.cometchat-users__item` | +| Item (active) | `.cometchat-users__item--active` | +| Item avatar | `.cometchat-users__item-avatar` | +| Item name | `.cometchat-users__item-name` | +| Item status | `.cometchat-users__item-status` | +| Section header | `.cometchat-users__section-header` | +| Empty state | `.cometchat-users__empty-state` | +| Error state | `.cometchat-users__error-state` | +| Loading state | `.cometchat-users__loading-state` | +| Selected preview | `.cometchat-users__selected-preview` | +| Selected chip | `.cometchat-users__selected-chip` | + +## Accessibility + +- List container: `role="listbox"` with `aria-label="Users list"` +- User items: `role="option"` with `aria-selected` +- Section headers: `role="separator"` with `aria-label` +- Loading state: `aria-busy="true"` +- Keyboard: `Tab` to focus, `ArrowUp`/`ArrowDown` to navigate, `Enter`/`Space` to select, `Escape` to clear search +- All icon-only buttons have `aria-label` +- `:focus-visible` styles on all interactive elements diff --git a/ui-kit/react/components/confirm-dialog.mdx b/ui-kit/react/components/confirm-dialog.mdx new file mode 100644 index 000000000..f5b8cd10f --- /dev/null +++ b/ui-kit/react/components/confirm-dialog.mdx @@ -0,0 +1,486 @@ +--- +title: "Confirm Dialog" +description: "A modal confirmation dialog with icon, title, message, and action buttons for destructive or important actions requiring explicit user confirmation." +--- + + +```json +{ + "component": "CometChatConfirmDialog", + "package": "@cometchat/chat-uikit-react", + "import": "import { CometChatConfirmDialog } from \"@cometchat/chat-uikit-react\";", + "cssImport": "import \"@cometchat/chat-uikit-react/css-variables.css\";", + "description": "A modal confirmation dialog with icon, title, message, and action buttons for destructive or important actions requiring explicit user confirmation.", + "cssRootClass": ".cometchat-confirm-dialog", + "primaryOutput": { + "prop": "onConfirm", + "type": "() => void | Promise" + }, + "props": { + "data": { + "title": { "type": "string", "default": "localized 'conversation_delete_title'" }, + "message": { "type": "string", "default": "localized 'conversation_delete_subtitle'" }, + "cancelText": { "type": "string", "default": "localized 'conversation_delete_confirm_no'" }, + "confirmText": { "type": "string", "default": "localized 'conversation_delete_confirm_yes'" }, + "errorText": { "type": "string", "default": "undefined" } + }, + "callbacks": { + "onClose": { "type": "() => void", "default": "undefined" }, + "onConfirm": { "type": "() => void | Promise", "default": "undefined" }, + "onCancel": { "type": "() => void", "default": "calls onClose" } + }, + "behavior": { + "isOpen": { "type": "boolean", "default": "undefined (uncontrolled)" }, + "closeOnOutsideClick": { "type": "boolean", "default": "true" }, + "variant": { "type": "'danger' | 'warning' | 'info'", "default": "'danger'" }, + "isLoading": { "type": "boolean", "default": "auto-managed from Promise" } + }, + "viewSlots": { + "icon": { "type": "ReactNode", "default": "variant-based delete icon" }, + "children (Content)": { "type": "ReactNode", "default": "title + message" }, + "children (Actions)": { "type": "ReactNode", "default": "cancel + confirm buttons" } + } + }, + "events": [], + "sdkListeners": [], + "types": { + "CometChatConfirmDialogVariant": "'danger' | 'warning' | 'info'" + } +} +``` + + +## Where It Fits + +`CometChatConfirmDialog` is a base modal component used whenever a destructive or important action needs explicit user confirmation. Wire it into feature components like `CometChatConversations` (delete conversation), `CometChatGroupMembers` (kick/ban member), or `CometChatMessageList` (image moderation) to gate critical actions behind a confirmation step. + +```tsx lines +import { useState } from "react"; +import { CometChatConfirmDialog } from "@cometchat/chat-uikit-react"; +import "@cometchat/chat-uikit-react/css-variables.css"; + +function App() { + const [showConfirm, setShowConfirm] = useState(false); + + const handleDelete = async () => { + await deleteConversation(conversationId); + }; + + return ( +
+ + setShowConfirm(false)} + variant="danger" + > + + + + +
+ ); +} +``` + +## Minimal Render + +```tsx lines +import { CometChatConfirmDialog } from "@cometchat/chat-uikit-react"; +import "@cometchat/chat-uikit-react/css-variables.css"; + +function Demo() { + return ( + {}}> + + + + + ); +} +``` + +Root CSS class: `.cometchat-confirm-dialog` + +## Actions and Events + +### Callback Props + +#### onConfirm + +Called when the confirm button is clicked. If it returns a `Promise`, the button automatically shows a loading state and catches errors. + +```tsx lines + { + await api.deleteConversation(id); + }} +/> +``` + +#### onCancel + +Called when the cancel button is clicked. Falls back to `onClose` from context if not provided. + +```tsx lines + { + console.log("User cancelled"); + setOpen(false); + }} +/> +``` + +#### onClose + +Called when the dialog requests to close (Escape key, outside click, or cancel button). + +```tsx lines + setOpen(false)} +> + {/* ... */} + +``` + +## Custom View Slots + +| Slot | Signature | Replaces | +| --- | --- | --- | +| `icon` (Icon) | `ReactNode` | Default variant-based icon | +| `children` (Content) | `ReactNode` | Title + message text | +| `children` (Actions) | `ReactNode` | Cancel + confirm buttons | + +### Custom Icon + +Replace the default delete icon with any React element. + + + +```tsx lines + + + + } +/> +``` + + +```css lines +/* The icon wrapper can be styled via the BEM class */ +.cometchat-confirm-dialog__icon { + background: #fff3e0; +} +``` + + + +### Custom Content + +Override the title/message with fully custom children. + + + +```tsx lines + +
+

Are you absolutely sure?

+

This will permanently remove all messages.

+

This cannot be undone.

+
+
+``` +
+ +```css lines +.cometchat-confirm-dialog__content { + gap: 8px; +} +``` + +
+ +### Custom Actions + +Replace the default buttons with fully custom action elements. + + + +```tsx lines + + + + +``` + + +```css lines +.cometchat-confirm-dialog__actions { + justify-content: flex-end; +} +``` + + + +## CSS Architecture + +The component uses CSS custom properties (design tokens) defined in `@cometchat/chat-uikit-react/css-variables.css`. The cascade: + +1. Global tokens set on the `.cometchat` root wrapper. +2. Component CSS (`.cometchat-confirm-dialog`) consumes these tokens via `var()`. +3. Overrides target `.cometchat-confirm-dialog` descendant selectors. + +### Key Selectors + +| Target | Selector | +| --- | --- | +| Backdrop | `.cometchat-confirm-dialog__backdrop` | +| Dialog container | `.cometchat-confirm-dialog` | +| Icon wrapper | `.cometchat-confirm-dialog__icon` | +| Content area | `.cometchat-confirm-dialog__content` | +| Title | `.cometchat-confirm-dialog__content-title` | +| Message | `.cometchat-confirm-dialog__content-message` | +| Actions row | `.cometchat-confirm-dialog__actions` | +| Cancel button | `.cometchat-confirm-dialog__actions-cancel` | +| Confirm button | `.cometchat-confirm-dialog__actions-confirm` | +| Error banner | `.cometchat-confirm-dialog__error` | + +### Example: Brand-themed dialog + +```css lines +.cometchat-confirm-dialog { + border-radius: 24px; + border-color: #e0e0e0; +} + +.cometchat-confirm-dialog__icon { + background: #fce4ec; +} + +.cometchat-confirm-dialog__actions-confirm--danger button { + background: #d32f2f; +} +``` + +### Customization Matrix + +| What to change | Where | Property/API | Example | +| --- | --- | --- | --- | +| Override behavior | Component props | `onConfirm`, `onCancel`, `onClose` | `onConfirm={handleDelete}` | +| Control open state | Component props | `isOpen`, `onClose` | `isOpen={showDialog}` | +| Change variant | Component props | `variant` | `variant="warning"` | +| Disable outside click | Component props | `closeOnOutsideClick` | `closeOnOutsideClick={false}` | +| Replace icon | Sub-component prop | `icon` on `Icon` | `} />` | +| Replace content | Sub-component children | `children` on `Content` | `` | +| Replace buttons | Sub-component children | `children` on `Actions` | `` | +| Change visual styling | Global CSS | `.cometchat-confirm-dialog` selectors | See CSS Selectors table | + +## Props + +All props are optional unless noted otherwise. + +--- + +### cancelText + +Text for the cancel button. + +| | | +| --- | --- | +| Type | `string` | +| Default | Localized `"Cancel"` | + +--- + +### children (Root) + +Sub-components to render inside the dialog. **Required on Root.** + +| | | +| --- | --- | +| Type | `ReactNode` | +| Default | `Icon + Content + Actions` | + +--- + +### className + +Optional custom CSS class name applied to the component root. + +| | | +| --- | --- | +| Type | `string` | +| Default | `undefined` | + +--- + +### closeOnOutsideClick + +Whether clicking outside the dialog closes it. + +| | | +| --- | --- | +| Type | `boolean` | +| Default | `true` | + +--- + +### confirmText + +Text for the confirm button. + +| | | +| --- | --- | +| Type | `string` | +| Default | Localized `"Confirm"` | + +--- + +### errorText + +Error message displayed above the action buttons. Auto-set when `onConfirm` rejects. + +| | | +| --- | --- | +| Type | `string` | +| Default | `undefined` | + +--- + +### icon + +Custom icon element for the Icon sub-component. + +| | | +| --- | --- | +| Type | `ReactNode` | +| Default | Variant-based delete icon | + +--- + +### isLoading + +Whether the confirm button shows a loading state. Auto-managed when `onConfirm` returns a Promise. + +| | | +| --- | --- | +| Type | `boolean` | +| Default | Auto-managed | + +--- + +### isOpen + +Whether the dialog is open. When provided, the component is controlled. + +| | | +| --- | --- | +| Type | `boolean` | +| Default | `undefined` (uncontrolled) | + +--- + +### message + +Descriptive message text in the Content sub-component. + +| | | +| --- | --- | +| Type | `string` | +| Default | Localized delete subtitle | + +--- + +### onCancel + +Callback when the cancel button is clicked. Falls back to `onClose`. + +| | | +| --- | --- | +| Type | `() => void` | +| Default | Calls `onClose` | + +--- + +### onClose + +Callback when the dialog requests to close. + +| | | +| --- | --- | +| Type | `() => void` | +| Default | `undefined` | + +--- + +### onConfirm + +Callback when the confirm button is clicked. Can return a Promise for async operations. + +| | | +| --- | --- | +| Type | `() => void \| Promise` | +| Default | `undefined` | + +--- + +### title + +Title text in the Content sub-component. + +| | | +| --- | --- | +| Type | `string` | +| Default | Localized delete title | + +--- + +### variant + +Visual variant affecting icon and confirm button color. + +| | | +| --- | --- | +| Type | `'danger' \| 'warning' \| 'info'` | +| Default | `'danger'` | + +```typescript +type CometChatConfirmDialogVariant = 'danger' | 'warning' | 'info'; +``` + +--- + +## CSS Selectors + +| Target | Selector | +| --- | --- | +| Backdrop overlay | `.cometchat-confirm-dialog__backdrop` | +| Dialog container | `.cometchat-confirm-dialog` | +| Icon wrapper | `.cometchat-confirm-dialog__icon` | +| Icon danger modifier | `.cometchat-confirm-dialog__icon--danger` | +| Icon warning modifier | `.cometchat-confirm-dialog__icon--warning` | +| Icon info modifier | `.cometchat-confirm-dialog__icon--info` | +| Default icon element | `.cometchat-confirm-dialog__icon-default` | +| Content area | `.cometchat-confirm-dialog__content` | +| Title text | `.cometchat-confirm-dialog__content-title` | +| Message text | `.cometchat-confirm-dialog__content-message` | +| Actions row | `.cometchat-confirm-dialog__actions` | +| Cancel button wrapper | `.cometchat-confirm-dialog__actions-cancel` | +| Confirm button wrapper | `.cometchat-confirm-dialog__actions-confirm` | +| Confirm danger modifier | `.cometchat-confirm-dialog__actions-confirm--danger` | +| Confirm warning modifier | `.cometchat-confirm-dialog__actions-confirm--warning` | +| Confirm info modifier | `.cometchat-confirm-dialog__actions-confirm--info` | +| Confirm loading modifier | `.cometchat-confirm-dialog__actions-confirm--loading` | +| Error banner | `.cometchat-confirm-dialog__error` | diff --git a/ui-kit/react/components/context-menu.mdx b/ui-kit/react/components/context-menu.mdx new file mode 100644 index 000000000..f1e501016 --- /dev/null +++ b/ui-kit/react/components/context-menu.mdx @@ -0,0 +1,567 @@ +--- +title: "Context Menu" +description: "A context menu that displays top-row icon actions and an overflow dropdown for additional options, used in message bubbles, list items, and headers." +--- + + +```json +{ + "component": "CometChatContextMenu", + "package": "@cometchat/chat-uikit-react", + "import": "import { CometChatContextMenu } from \"@cometchat/chat-uikit-react\";", + "cssImport": "import \"@cometchat/chat-uikit-react/css-variables.css\";", + "description": "A context menu that displays top-row icon actions and an overflow dropdown for additional options.", + "cssRootClass": ".cometchat-context-menu", + "subComponents": ["Root", "Item", "Trigger", "Dropdown"], + "props": { + "Root": { + "items": { "type": "CometChatContextMenuItemData[]", "default": "[]" }, + "topMenuSize": { "type": "number", "default": "2" }, + "onOptionClicked": { "type": "(item: CometChatContextMenuItemData) => void", "default": "undefined" }, + "placement": { "type": "CometChatContextMenuPlacement", "default": "'left'" }, + "moreButtonTooltip": { "type": "string", "default": "undefined" }, + "closeOnOutsideClick": { "type": "boolean", "default": "true" }, + "className": { "type": "string", "default": "undefined" }, + "children": { "type": "ReactNode", "default": "undefined" } + }, + "Item": { + "item": { "type": "CometChatContextMenuItemData", "default": "undefined", "note": "Required." }, + "variant": { "type": "'icon' | 'full'", "default": "'full'" }, + "className": { "type": "string", "default": "undefined" } + }, + "Trigger": { + "tooltip": { "type": "string", "default": "undefined" }, + "className": { "type": "string", "default": "undefined" }, + "children": { "type": "ReactNode", "default": "undefined" } + }, + "Dropdown": { + "placement": { "type": "CometChatContextMenuPlacement", "default": "inherited from Root" }, + "className": { "type": "string", "default": "undefined" }, + "children": { "type": "ReactNode", "default": "undefined" } + } + }, + "types": { + "CometChatContextMenuItemData": { + "id": "string", + "title": "string", + "icon": "ReactNode (optional)", + "iconURL": "string (optional)", + "onClick": "() => void", + "disabled": "boolean (optional)", + "className": "string (optional)" + }, + "CometChatContextMenuPlacement": "'top' | 'right' | 'bottom' | 'left'", + "CometChatContextMenuContextValue": { + "isOpen": "boolean", + "open": "() => void", + "close": "() => void", + "toggle": "() => void", + "placement": "CometChatContextMenuPlacement", + "onOptionClicked": "(item: CometChatContextMenuItemData) => void | undefined", + "triggerRef": "RefObject" + } + } +} +``` + + +## Where It Fits + +`CometChatContextMenu` is a base component used as the overflow action menu across the UI Kit. It appears on message bubbles, conversation list items, group member rows, user list items, and message headers. It splits actions into a visible top row of icon buttons and a dropdown for the rest. + +```tsx lines +import { CometChatContextMenu } from "@cometchat/chat-uikit-react"; +import "@cometchat/chat-uikit-react/css-variables.css"; + +const options = [ + { id: "edit", title: "Edit", icon: , onClick: () => handleEdit() }, + { id: "copy", title: "Copy", icon: , onClick: () => handleCopy() }, + { id: "info", title: "Info", icon: , onClick: () => handleInfo() }, + { id: "delete", title: "Delete", icon: , onClick: () => handleDelete() }, +]; + +function MessageBubbleActions() { + return ( + console.log("Selected:", item.id)} + /> + ); +} +``` + +## Minimal Render + +```tsx lines +import { CometChatContextMenu } from "@cometchat/chat-uikit-react"; +import "@cometchat/chat-uikit-react/css-variables.css"; + +function Demo() { + return ( + {} }, + { id: "2", title: "Delete", onClick: () => {} }, + ]} + topMenuSize={1} + /> + ); +} +``` + +Root CSS class: `.cometchat-context-menu` + +## Sub-Components + +`CometChatContextMenu` is a compound component with four sub-components: + +| Sub-component | Purpose | +| --- | --- | +| `Root` | Container that provides context, orchestrates top-row items and dropdown. | +| `Item` | A single action rendered as a button. Supports `icon` (top-row) and `full` (dropdown) variants. | +| `Trigger` | The "more" button that toggles the dropdown. | +| `Dropdown` | The overflow popover with keyboard navigation and focus trap. | + +### Root + +The outermost wrapper. In data-driven mode, pass `items` and `topMenuSize` and it renders everything automatically. For full control, pass `children` instead. + + + +```tsx lines + +``` + + +```tsx lines + + + + + + + + +``` + + + +### Item + +Renders a single action. In `icon` variant, it shows only the icon with an `aria-label`. In `full` variant, it shows icon + title and uses `role="menuitem"`. + +```tsx lines +, + onClick: () => handleEdit(), + }} + variant="full" +/> +``` + +### Trigger + +The "more" button. Renders a vertical ellipsis icon by default. Pass `children` for a custom trigger. + +```tsx lines + + + +``` + +### Dropdown + +The overflow popover. Positioned relative to the root container using the `placement` prop. Includes full keyboard navigation and a focus trap. + +```tsx lines + + + + +``` + +## Actions and Events + +### Callback Props + +#### onOptionClicked + +Called when any menu item is selected (top-row or dropdown). Receives the full `CometChatContextMenuItemData` object. When provided, overrides individual `item.onClick` callbacks. + +```tsx lines + { + console.log("Selected action:", item.id, item.title); + }} +/> +``` + +## Custom View Slots + +| Slot | Signature | Replaces | +| --- | --- | --- | +| `children` on `Root` | `ReactNode` | Entire auto-generated layout (top-row + trigger + dropdown) | +| `children` on `Trigger` | `ReactNode` | Default "more" icon | +| `children` on `Dropdown` | `ReactNode` | Auto-generated dropdown items | + +### Custom trigger content + +```tsx lines + + + + + + + + + + +``` + +## Common Patterns + +### Message bubble options + +```tsx lines +import { CometChatContextMenu } from "@cometchat/chat-uikit-react"; + +function MessageOptions({ options }) { + return ( + + ); +} +``` + +### All items in dropdown (no top row) + +```tsx lines + +``` + +### All items in top row (no dropdown) + +```tsx lines + +``` + +## Keyboard Navigation + +The context menu is fully keyboard-accessible: + +| Key | Behavior | +| --- | --- | +| `Tab` | Moves focus between top-row items and the trigger button | +| `Enter` / `Space` | On top-row item: activates it. On trigger: toggles dropdown | +| `ArrowDown` | On trigger: opens dropdown. In dropdown: moves to next item (wraps) | +| `ArrowUp` | In dropdown: moves to previous item (wraps) | +| `Home` | In dropdown: moves focus to first item | +| `End` | In dropdown: moves focus to last item | +| `Escape` | Closes dropdown and returns focus to trigger | +| `Tab` (in dropdown) | Cycles within dropdown items (focus trap) | + +When the dropdown opens, focus moves to the first enabled item. When it closes, focus returns to the trigger button. + +## CSS Architecture + +The component uses CSS custom properties (design tokens) defined in `@cometchat/chat-uikit-react/css-variables.css`. The cascade: + +1. Global tokens set on the `.cometchat` root wrapper. +2. Component CSS (`.cometchat-context-menu`) consumes these tokens via `var()`. +3. Overrides target `.cometchat-context-menu` descendant selectors. + +### Key Selectors + +| Target | Selector | +| --- | --- | +| Root container | `.cometchat-context-menu` | +| Top menu row | `.cometchat-context-menu__top-menu` | +| Top menu item | `.cometchat-context-menu__top-menu-item` | +| Top menu item icon | `.cometchat-context-menu__top-menu-item-icon` | +| Trigger button | `.cometchat-context-menu__trigger` | +| Trigger icon | `.cometchat-context-menu__trigger-icon` | +| Dropdown | `.cometchat-context-menu__dropdown` | +| Dropdown item | `.cometchat-context-menu__dropdown-item` | +| Dropdown item icon | `.cometchat-context-menu__dropdown-item-icon` | +| Dropdown item title | `.cometchat-context-menu__dropdown-item-title` | + +### Example: Brand-themed context menu + +```css lines title="App.css" +.cometchat-context-menu__dropdown { + border-radius: 12px; + border-color: var(--brand-border); +} + +.cometchat-context-menu__dropdown-item:hover:not(:disabled) { + background: var(--brand-hover); +} + +.cometchat-context-menu__top-menu-item:hover:not(:disabled) { + background: var(--brand-hover); +} +``` + +### Customization Matrix + +| What to change | Where | Property/API | Example | +| --- | --- | --- | --- | +| Menu items | Component props | `items` on `Root` | `` | +| Top row count | Component props | `topMenuSize` on `Root` | `` | +| Dropdown position | Component props | `placement` on `Root` or `Dropdown` | `` | +| Handle selection | Component props | `onOptionClicked` on `Root` | `` | +| Disable an item | Item data | `disabled` on `CometChatContextMenuItemData` | `{ disabled: true }` | +| Custom trigger | Sub-component | `children` on `Trigger` | `` | +| Change visual styling | Global CSS | `.cometchat-context-menu` selectors | See example above | + +## Props + +All props are optional unless noted otherwise. + +--- + +### CometChatContextMenu.Root + +#### items + +Array of menu item data objects. When provided without `children`, the component auto-renders top-row items and dropdown. + +| | | +| --- | --- | +| Type | `CometChatContextMenuItemData[]` | +| Default | `[]` | + +```typescript +interface CometChatContextMenuItemData { + id: string; + title: string; + icon?: ReactNode; + iconURL?: string; + onClick: () => void; + disabled?: boolean; + className?: string; +} +``` + +--- + +#### topMenuSize + +Number of items visible in the top row. Remaining items go to the dropdown. When `0`, all items are in the dropdown. When `>= items.length`, no dropdown is rendered. + +| | | +| --- | --- | +| Type | `number` | +| Default | `2` | + +--- + +#### onOptionClicked + +Called when any menu item is selected. Receives the full item data object. When provided, overrides individual `item.onClick` callbacks. + +| | | +| --- | --- | +| Type | `(item: CometChatContextMenuItemData) => void` | +| Default | `undefined` | + +--- + +#### placement + +Position of the dropdown relative to the trigger. + +| | | +| --- | --- | +| Type | `'top' \| 'right' \| 'bottom' \| 'left'` | +| Default | `'left'` | + +--- + +#### moreButtonTooltip + +Tooltip text for the "more" trigger button. + +| | | +| --- | --- | +| Type | `string` | +| Default | `undefined` | + +--- + +#### closeOnOutsideClick + +Whether clicking outside the component closes the dropdown. + +| | | +| --- | --- | +| Type | `boolean` | +| Default | `true` | + +--- + +#### className + +Custom CSS class appended to the root container. + +| | | +| --- | --- | +| Type | `string` | +| Default | `undefined` | + +--- + +#### children + +Custom content. When provided, overrides the data-driven rendering entirely. + +| | | +| --- | --- | +| Type | `ReactNode` | +| Default | `undefined` | + +--- + +### CometChatContextMenu.Item + +#### item + +The menu item data object. + +| | | +| --- | --- | +| Type | `CometChatContextMenuItemData` | +| Default | `undefined` | + +**Required.** + +--- + +#### variant + +Display mode. `icon` renders icon-only (for top row). `full` renders icon + title (for dropdown). + +| | | +| --- | --- | +| Type | `'icon' \| 'full'` | +| Default | `'full'` | + +--- + +#### className + +Custom CSS class appended to the item button. + +| | | +| --- | --- | +| Type | `string` | +| Default | `undefined` | + +--- + +### CometChatContextMenu.Trigger + +#### tooltip + +Tooltip and `aria-label` text for the trigger button. + +| | | +| --- | --- | +| Type | `string` | +| Default | `undefined` | + +--- + +#### className + +Custom CSS class appended to the trigger button. + +| | | +| --- | --- | +| Type | `string` | +| Default | `undefined` | + +--- + +#### children + +Custom trigger content. Replaces the default vertical ellipsis icon. + +| | | +| --- | --- | +| Type | `ReactNode` | +| Default | `undefined` | + +--- + +### CometChatContextMenu.Dropdown + +#### placement + +Position of the dropdown. Overrides the value from `Root` context. + +| | | +| --- | --- | +| Type | `'top' \| 'right' \| 'bottom' \| 'left'` | +| Default | inherited from `Root` | + +--- + +#### className + +Custom CSS class appended to the dropdown container. + +| | | +| --- | --- | +| Type | `string` | +| Default | `undefined` | + +--- + +#### children + +Dropdown content. Typically `CometChatContextMenu.Item` elements with `variant="full"`. + +| | | +| --- | --- | +| Type | `ReactNode` | +| Default | `undefined` | + +--- + +## CSS Selectors + +| Target | Selector | +| --- | --- | +| Root | `.cometchat-context-menu` | +| Top menu row | `.cometchat-context-menu__top-menu` | +| Top menu item | `.cometchat-context-menu__top-menu-item` | +| Top menu item icon | `.cometchat-context-menu__top-menu-item-icon` | +| Trigger button | `.cometchat-context-menu__trigger` | +| Trigger icon | `.cometchat-context-menu__trigger-icon` | +| Dropdown | `.cometchat-context-menu__dropdown` | +| Dropdown (top) | `.cometchat-context-menu__dropdown--top` | +| Dropdown (right) | `.cometchat-context-menu__dropdown--right` | +| Dropdown (bottom) | `.cometchat-context-menu__dropdown--bottom` | +| Dropdown (left) | `.cometchat-context-menu__dropdown--left` | +| Dropdown item | `.cometchat-context-menu__dropdown-item` | +| Dropdown item (disabled) | `.cometchat-context-menu__dropdown-item--disabled` | +| Dropdown item icon | `.cometchat-context-menu__dropdown-item-icon` | +| Dropdown item title | `.cometchat-context-menu__dropdown-item-title` | diff --git a/ui-kit/react/components/conversation-starter.mdx b/ui-kit/react/components/conversation-starter.mdx new file mode 100644 index 000000000..c28de829d --- /dev/null +++ b/ui-kit/react/components/conversation-starter.mdx @@ -0,0 +1,548 @@ +--- +title: "Conversation Starter" +description: "Displays AI-generated conversation starter suggestions as clickable pill-shaped buttons, managing loading, loaded, error, and empty states." +--- + + +```json +{ + "component": "CometChatConversationStarter", + "package": "@cometchat/chat-uikit-react", + "import": "import { CometChatConversationStarter } from \"@cometchat/chat-uikit-react\";", + "cssImport": "import \"@cometchat/chat-uikit-react/css-variables.css\";", + "description": "Displays AI-generated conversation starter suggestions as clickable pill-shaped buttons.", + "cssRootClass": ".cometchat-conversation-starter", + "subComponents": ["Root", "Item", "Loading", "Error", "Empty"], + "primaryOutput": { + "prop": "onSuggestionClick", + "type": "(suggestion: string) => void" + }, + "props": { + "Root": { + "getConversationStarters": { "type": "() => Promise", "note": "Required." }, + "onSuggestionClick": { "type": "(suggestion: string) => void", "default": "undefined" }, + "className": { "type": "string", "default": "undefined" }, + "children": { "type": "ReactNode", "default": "undefined" } + }, + "Item": { + "suggestion": { "type": "string", "note": "Required." }, + "onClick": { "type": "(suggestion: string) => void", "default": "undefined" }, + "disabled": { "type": "boolean", "default": "false" }, + "className": { "type": "string", "default": "undefined" } + }, + "Loading": { + "count": { "type": "number", "default": "3" }, + "className": { "type": "string", "default": "undefined" }, + "children": { "type": "ReactNode", "default": "undefined" } + }, + "Error": { + "message": { "type": "string", "default": "\"Failed to load conversation starters.\"" }, + "onRetry": { "type": "() => void", "default": "undefined" }, + "className": { "type": "string", "default": "undefined" }, + "children": { "type": "ReactNode", "default": "undefined" } + }, + "Empty": { + "message": { "type": "string", "default": "undefined" }, + "className": { "type": "string", "default": "undefined" }, + "children": { "type": "ReactNode", "default": "undefined" } + } + }, + "types": { + "CometChatConversationStarterState": "'loading' | 'loaded' | 'error' | 'empty'", + "CometChatConversationStarterContextValue": { + "state": "CometChatConversationStarterState", + "suggestions": "string[]", + "error": "Error | null", + "onSuggestionClick": "(suggestion: string) => void | undefined", + "retry": "() => void" + } + } +} +``` + + +## Where It Fits + +`CometChatConversationStarter` is a base component that displays AI-generated conversation suggestions as pill-shaped buttons. It is typically used inside a message composer area or an empty chat view to help users start a conversation. The consumer provides a `getConversationStarters` function (usually from an AI plugin or custom service), and the component handles loading, error, and empty states automatically. + +```tsx lines +import { CometChatConversationStarter } from "@cometchat/chat-uikit-react"; +import "@cometchat/chat-uikit-react/css-variables.css"; + +function ChatView() { + const fetchStarters = () => + fetch("/api/ai/starters").then((r) => r.json()); + + const handleSuggestionClick = (suggestion: string) => { + console.log("Send message:", suggestion); + }; + + return ( +
+ + + + + +
+ ); +} +``` + +## Minimal Render + +```tsx lines +import { CometChatConversationStarter } from "@cometchat/chat-uikit-react"; +import "@cometchat/chat-uikit-react/css-variables.css"; + +function Demo() { + return ( + Promise.resolve(["How are you?", "What's new?"])} + onSuggestionClick={(s) => console.log(s)} + > + + + + ); +} +``` + +Root CSS class: `.cometchat-conversation-starter` + +## Actions and Events + +### Callback Props + +#### onSuggestionClick + +Called when a user clicks a suggestion button. Receives the suggestion string as the argument. + +```tsx lines + { + sendMessage(suggestion); + }} +> + + +``` + +#### onRetry (Error sub-component) + +Called when the user clicks the retry button in the error state. If not provided, the component uses the built-in `retry()` method from context which re-calls `getConversationStarters`. + +```tsx lines + { + console.log("Retrying..."); + }} +/> +``` + +## Custom View Slots + +| Slot | Signature | Replaces | +| --- | --- | --- | +| `Loading` | `{ count?, className?, children? }` | Shimmer loading state | +| `Error` | `{ message?, onRetry?, className?, children? }` | Error state view | +| `Empty` | `{ message?, className?, children? }` | Empty state view | + +### Loading + +Renders shimmer placeholder pills while suggestions are being fetched. Defaults to 3 shimmer items. + + + +```tsx lines + +``` + + +```tsx lines + +``` + + +```tsx lines + +
Loading suggestions...
+
+``` +
+
+ +### Error + +Renders when `getConversationStarters` rejects. Shows a localized error message and an optional retry button. + + + +```tsx lines + +``` + + +```tsx lines + console.log("retry")} +/> +``` + + +```tsx lines + +
+

Something went wrong

+ +
+
+``` +
+
+ +### Empty + +Renders when `getConversationStarters` resolves with an empty array. By default renders nothing unless a `message` or `children` is provided. + +```tsx lines + +``` + +## Common Patterns + +### Retry on error + +```tsx lines +import { CometChatConversationStarter } from "@cometchat/chat-uikit-react"; +import "@cometchat/chat-uikit-react/css-variables.css"; + +function StartersWithRetry() { + const fetchStarters = () => + fetch("/api/ai/starters").then((r) => r.json()); + + return ( + console.log(s)} + > + + + + + ); +} +``` + +### Using context in custom children + +```tsx lines +import { useCometChatConversationStarterContext } from "@cometchat/chat-uikit-react"; + +function CustomSuggestionList() { + const { state, suggestions, onSuggestionClick } = + useCometChatConversationStarterContext(); + + if (state !== "loaded") return null; + + return ( +
    + {suggestions.map((s) => ( +
  • + +
  • + ))} +
+ ); +} +``` + +## CSS Architecture + +The component uses CSS custom properties (design tokens) defined in `@cometchat/chat-uikit-react/css-variables.css`. The cascade: + +1. Global tokens set on the `.cometchat` root wrapper. +2. Component CSS (`.cometchat-conversation-starter`) consumes these tokens via `var()`. +3. Overrides target `.cometchat-conversation-starter` descendant selectors. + +### Key Selectors + +| Target | Selector | +| --- | --- | +| Root container | `.cometchat-conversation-starter` | +| Suggestion pill | `.cometchat-conversation-starter__item` | +| Suggestion button | `.cometchat-conversation-starter__item-button` | +| Shimmer container | `.cometchat-conversation-starter__shimmer-container` | +| Shimmer pill | `.cometchat-conversation-starter__shimmer-item` | +| Error view | `.cometchat-conversation-starter__error-view` | +| Retry button | `.cometchat-conversation-starter__error-retry` | +| Empty view | `.cometchat-conversation-starter__empty-view` | +| Disabled modifier | `.cometchat-conversation-starter__item--disabled` | + +### Example: Brand-themed conversation starters + +```css lines title="App.css" +.cometchat-conversation-starter__item { + border-color: var(--brand-border); +} + +.cometchat-conversation-starter__item:hover { + background: var(--brand-hover); +} + +.cometchat-conversation-starter__item-button { + color: var(--brand-text); + font-family: var(--brand-font); +} +``` + +### Customization Matrix + +| What to change | Where | Property/API | Example | +| --- | --- | --- | --- | +| Data source | Component props | `getConversationStarters` on `Root` | `` | +| Click handler | Component props | `onSuggestionClick` on `Root` | `` | +| Loading count | Component props | `count` on `Loading` | `` | +| Error message | Component props | `message` on `Error` | `` | +| Retry behavior | Component props | `onRetry` on `Error` | `` | +| Replace loading UI | Component props | `children` on `Loading` | `` | +| Replace error UI | Component props | `children` on `Error` | `` | +| Change visual styling | Global CSS | `.cometchat-conversation-starter` selectors | See example above | + +## Props + +All props are optional unless noted otherwise. + +--- + +### CometChatConversationStarter.Root + +#### getConversationStarters + +Async function that returns an array of suggestion strings. Called on mount and on retry. + +| | | +| --- | --- | +| Type | `() => Promise` | +| Default | `undefined` | + +**Required.** + +--- + +#### onSuggestionClick + +Called when a suggestion button is clicked. Receives the suggestion string. + +| | | +| --- | --- | +| Type | `(suggestion: string) => void` | +| Default | `undefined` | + +--- + +#### className + +Custom CSS class appended to the root container. + +| | | +| --- | --- | +| Type | `string` | +| Default | `undefined` | + +--- + +#### children + +Sub-components for custom composition (`Loading`, `Error`, `Empty`). + +| | | +| --- | --- | +| Type | `ReactNode` | +| Default | `undefined` | + +--- + +### CometChatConversationStarter.Item + +#### suggestion + +The suggestion text to display inside the button. + +| | | +| --- | --- | +| Type | `string` | +| Default | `undefined` | + +**Required.** + +--- + +#### onClick + +Called when this specific item is clicked. Receives the suggestion string. + +| | | +| --- | --- | +| Type | `(suggestion: string) => void` | +| Default | `undefined` | + +--- + +#### disabled + +Whether the item is disabled. Disabled items cannot be clicked and show reduced opacity. + +| | | +| --- | --- | +| Type | `boolean` | +| Default | `false` | + +--- + +#### className + +Custom CSS class appended to the item container. + +| | | +| --- | --- | +| Type | `string` | +| Default | `undefined` | + +--- + +### CometChatConversationStarter.Loading + +#### count + +Number of shimmer placeholder items to display. + +| | | +| --- | --- | +| Type | `number` | +| Default | `3` | + +--- + +#### className + +Custom CSS class appended to the shimmer container. + +| | | +| --- | --- | +| Type | `string` | +| Default | `undefined` | + +--- + +#### children + +Custom loading content. When provided, replaces the default shimmer animation. + +| | | +| --- | --- | +| Type | `ReactNode` | +| Default | `undefined` | + +--- + +### CometChatConversationStarter.Error + +#### message + +Custom error message text. Overrides the default localized error text. + +| | | +| --- | --- | +| Type | `string` | +| Default | `"Failed to load conversation starters."` | + +--- + +#### onRetry + +Callback for the retry button. If not provided, uses the built-in `retry()` from context. + +| | | +| --- | --- | +| Type | `() => void` | +| Default | `undefined` | + +--- + +#### className + +Custom CSS class appended to the error container. + +| | | +| --- | --- | +| Type | `string` | +| Default | `undefined` | + +--- + +#### children + +Custom error content. When provided, replaces the default error message and retry button. + +| | | +| --- | --- | +| Type | `ReactNode` | +| Default | `undefined` | + +--- + +### CometChatConversationStarter.Empty + +#### message + +Text to display when no suggestions are available. If not provided and no children, renders nothing. + +| | | +| --- | --- | +| Type | `string` | +| Default | `undefined` | + +--- + +#### className + +Custom CSS class appended to the empty container. + +| | | +| --- | --- | +| Type | `string` | +| Default | `undefined` | + +--- + +#### children + +Custom empty content. When provided, replaces the default empty message. + +| | | +| --- | --- | +| Type | `ReactNode` | +| Default | `undefined` | + +--- + +## CSS Selectors + +| Target | Selector | +| --- | --- | +| Root | `.cometchat-conversation-starter` | +| Suggestion pill | `.cometchat-conversation-starter__item` | +| Suggestion button | `.cometchat-conversation-starter__item-button` | +| Disabled item | `.cometchat-conversation-starter__item--disabled` | +| Shimmer container | `.cometchat-conversation-starter__shimmer-container` | +| Shimmer pill | `.cometchat-conversation-starter__shimmer-item` | +| Error view | `.cometchat-conversation-starter__error-view` | +| Retry button | `.cometchat-conversation-starter__error-retry` | +| Empty view | `.cometchat-conversation-starter__empty-view` | diff --git a/ui-kit/react/components/conversation-summary.mdx b/ui-kit/react/components/conversation-summary.mdx new file mode 100644 index 000000000..d3cd3c51c --- /dev/null +++ b/ui-kit/react/components/conversation-summary.mdx @@ -0,0 +1,412 @@ +--- +title: "Conversation Summary" +description: "Displays an AI-generated conversation summary inside a card with a header, close button, and body, managing loading, loaded, error, and empty states." +--- + + +```json +{ + "component": "CometChatConversationSummary", + "package": "@cometchat/chat-uikit-react", + "import": "import { CometChatConversationSummary } from \"@cometchat/chat-uikit-react\";", + "cssImport": "import \"@cometchat/chat-uikit-react/css-variables.css\";", + "description": "Displays an AI-generated conversation summary inside a card with a header, close button, and body.", + "cssRootClass": ".cometchat-conversation-summary", + "subComponents": ["Root", "Header", "Body", "Loading", "Error", "Empty"], + "primaryOutput": { + "prop": "onClose", + "type": "() => void" + }, + "props": { + "Root": { + "getConversationSummary": { "type": "() => Promise", "note": "Required." }, + "onClose": { "type": "() => void", "default": "undefined" }, + "className": { "type": "string", "default": "undefined" }, + "children": { "type": "ReactNode", "default": "undefined" } + }, + "Header": { + "title": { "type": "string", "default": "\"Conversation summary\"" }, + "showCloseButton": { "type": "boolean", "default": "true" }, + "className": { "type": "string", "default": "undefined" }, + "children": { "type": "ReactNode", "default": "undefined" } + }, + "Body": { + "className": { "type": "string", "default": "undefined" }, + "children": { "type": "ReactNode", "default": "undefined" } + }, + "Loading": { + "count": { "type": "number", "default": "3" }, + "className": { "type": "string", "default": "undefined" }, + "children": { "type": "ReactNode", "default": "undefined" } + }, + "Error": { + "message": { "type": "string", "default": "\"Looks like something went wrong\"" }, + "onRetry": { "type": "() => void", "default": "undefined" }, + "className": { "type": "string", "default": "undefined" }, + "children": { "type": "ReactNode", "default": "undefined" } + }, + "Empty": { + "message": { "type": "string", "default": "\"No Summary Available\"" }, + "className": { "type": "string", "default": "undefined" }, + "children": { "type": "ReactNode", "default": "undefined" } + } + }, + "types": { + "CometChatConversationSummaryState": "'loading' | 'loaded' | 'error' | 'empty'", + "CometChatConversationSummaryContextValue": { + "state": "CometChatConversationSummaryState", + "summary": "string", + "error": "Error | null", + "onClose": "(() => void) | undefined", + "retry": "() => void" + } + } +} +``` + + +## Where It Fits + +`CometChatConversationSummary` is a base component that displays an AI-generated summary of a conversation inside a card. It is typically rendered inside a message list panel or a sidebar to give users a quick overview of the conversation. The consumer provides a `getConversationSummary` function (usually from an AI plugin or custom service), and the component handles loading, error, and empty states automatically. + +```tsx lines +import { CometChatConversationSummary } from "@cometchat/chat-uikit-react"; +import "@cometchat/chat-uikit-react/css-variables.css"; + +function ChatPanel() { + const fetchSummary = () => + fetch("/api/ai/summary").then((r) => r.text()); + + return ( +
+ console.log("Closed")} + > + + + + + + +
+ ); +} +``` + +## Minimal Render + +```tsx lines +import { CometChatConversationSummary } from "@cometchat/chat-uikit-react"; +import "@cometchat/chat-uikit-react/css-variables.css"; + +function Demo() { + return ( + Promise.resolve("Meeting discussed Q2 goals.")} + > + + + + ); +} +``` + +Root CSS class: `.cometchat-conversation-summary` + +## Actions and Events + +### Callback Props + +#### onClose + +Called when the user clicks the close button or presses the Escape key while the component is focused. + +```tsx lines + setShowSummary(false)} +> + + + +``` + +#### onRetry (Error sub-component) + +Called when the user clicks the retry button in the error state. Falls back to the internal `retry()` method if not provided. + +```tsx lines + refetchSummary()} +/> +``` + +## Custom View Slots + +| Slot | Sub-component | Replaces | +| --- | --- | --- | +| Header | `` | Default header with title and close button | +| Body | `` | Default summary text rendering | +| Loading | `` | Default shimmer bars | +| Error | `` | Default error message with retry | +| Empty | `` | Default empty message | + +### Custom Header + +Pass `children` to `Header` to replace the default title and close button. + +```tsx lines + +
+ My Custom Title + +
+
+``` + +### Custom Error with Retry + +Pass `children` to `Error` to fully replace the error view. + +```tsx lines + +
+

Something went wrong

+ +
+
+``` + +### Custom Loading + +Pass `children` to `Loading` to replace the default shimmer bars. + +```tsx lines + +
Loading summary...
+
+``` + +## Common Patterns + +### Without Header (Headless Usage) + +Omit the `Header` sub-component to render just the body content. + +```tsx lines + + + + +``` + +### Custom Header Title + +```tsx lines + + + + + +``` + +### Without Close Button + +```tsx lines + + + + + +``` + +## CSS Architecture + +The component uses CSS custom properties (design tokens) defined in `@cometchat/chat-uikit-react/css-variables.css`. The cascade: + +1. Global tokens set on the `.cometchat` root wrapper. +2. Component CSS (`.cometchat-conversation-summary`) consumes these tokens via `var()`. +3. Overrides target `.cometchat-conversation-summary` descendant selectors. + +### Key Selectors + +| Target | Selector | +| --- | --- | +| Root card | `.cometchat-conversation-summary` | +| Header row | `.cometchat-conversation-summary__header` | +| Header title | `.cometchat-conversation-summary__header-title` | +| Close button | `.cometchat-conversation-summary__header-close-button` | +| Body | `.cometchat-conversation-summary__body` | +| Shimmer container | `.cometchat-conversation-summary__shimmer-container` | +| Shimmer bar | `.cometchat-conversation-summary__shimmer-item` | +| Error view | `.cometchat-conversation-summary__error-view` | +| Retry button | `.cometchat-conversation-summary__error-retry` | +| Empty view | `.cometchat-conversation-summary__empty-view` | + +### Example: Brand-themed summary card + +```css lines title="App.css" +.cometchat-conversation-summary { + border-color: #6851ff; + box-shadow: 0 4px 12px rgba(104, 81, 255, 0.15); +} + +.cometchat-conversation-summary__header-title { + color: #6851ff; +} + +.cometchat-conversation-summary__error-retry { + color: #6851ff; + border-color: #6851ff; +} +``` + +### Customization Matrix + +| What to change | Where | Property/API | Example | +| --- | --- | --- | --- | +| Close behavior | Root props | `onClose` callback | `onClose={() => hide()}` | +| Header text | Header props | `title` | `title="Chat Summary"` | +| Hide close button | Header props | `showCloseButton` | `showCloseButton={false}` | +| Error message | Error props | `message` | `message="Failed"` | +| Retry behavior | Error props | `onRetry` | `onRetry={() => refetch()}` | +| Empty message | Empty props | `message` | `message="Nothing here"` | +| Shimmer count | Loading props | `count` | `count={5}` | +| Replace any section | Sub-component | `children` | Pass custom JSX | +| Change visual styling | Global CSS | `.cometchat-conversation-summary` selectors | See CSS Selectors | + +## Props + +All props are optional unless noted otherwise. + +--- + +### getConversationSummary (Root) + +Async function that returns a summary string. **Required.** + +| | | +| --- | --- | +| Type | `() => Promise` | +| Default | — | + +--- + +### onClose (Root) + +Callback when the close button is clicked or Escape is pressed. + +| | | +| --- | --- | +| Type | `() => void` | +| Default | `undefined` | + +--- + +### className (Root, Header, Body, Loading, Error, Empty) + +Optional custom CSS class name appended to the component's root element. + +| | | +| --- | --- | +| Type | `string` | +| Default | `undefined` | + +--- + +### children (Root, Header, Body, Loading, Error, Empty) + +Custom content that replaces the default rendering of the sub-component. + +| | | +| --- | --- | +| Type | `ReactNode` | +| Default | `undefined` | + +--- + +### title (Header) + +Custom title text displayed in the header. + +| | | +| --- | --- | +| Type | `string` | +| Default | `"Conversation summary"` | + +--- + +### showCloseButton (Header) + +Whether to show the close button in the header. + +| | | +| --- | --- | +| Type | `boolean` | +| Default | `true` | + +--- + +### count (Loading) + +Number of shimmer bars to display during loading. + +| | | +| --- | --- | +| Type | `number` | +| Default | `3` | + +--- + +### message (Error) + +Custom error message text. + +| | | +| --- | --- | +| Type | `string` | +| Default | `"Looks like something went wrong"` | + +--- + +### onRetry (Error) + +Callback to retry fetching the summary. Falls back to the internal retry mechanism if not provided. + +| | | +| --- | --- | +| Type | `() => void` | +| Default | `undefined` | + +--- + +### message (Empty) + +Custom empty state message text. + +| | | +| --- | --- | +| Type | `string` | +| Default | `"No Summary Available"` | + +--- + +## CSS Selectors + +| Target | Selector | +| --- | --- | +| Root card | `.cometchat-conversation-summary` | +| Header row | `.cometchat-conversation-summary__header` | +| Header title | `.cometchat-conversation-summary__header-title` | +| Close button | `.cometchat-conversation-summary__header-close-button` | +| Body content | `.cometchat-conversation-summary__body` | +| Shimmer container | `.cometchat-conversation-summary__shimmer-container` | +| Shimmer bar | `.cometchat-conversation-summary__shimmer-item` | +| Error view | `.cometchat-conversation-summary__error-view` | +| Retry button | `.cometchat-conversation-summary__error-retry` | +| Empty view | `.cometchat-conversation-summary__empty-view` | diff --git a/ui-kit/react/components/conversations.mdx b/ui-kit/react/components/conversations.mdx new file mode 100644 index 000000000..974e848c7 --- /dev/null +++ b/ui-kit/react/components/conversations.mdx @@ -0,0 +1,713 @@ +--- +title: "Conversations" +description: "Scrollable list of recent one-on-one and group conversations for the logged-in user with real-time updates." +--- + + +```json +{ + "component": "CometChatConversations", + "package": "@cometchat/chat-uikit-react", + "import": "import { CometChatConversations } from \"@cometchat/chat-uikit-react\";", + "cssImport": "import \"@cometchat/chat-uikit-react/css-variables.css\";", + "description": "Scrollable list of recent one-on-one and group conversations for the logged-in user with real-time updates.", + "cssRootClass": ".cometchat-conversations", + "primaryOutput": { + "prop": "onItemClick", + "type": "(conversation: CometChat.Conversation) => void" + }, + "props": { + "data": { + "conversationsRequestBuilder": { + "type": "CometChat.ConversationsRequestBuilder", + "default": "SDK default (30 per page)", + "note": "Pass the builder instance, not the result of .build()" + }, + "searchRequestBuilder": { + "type": "CometChat.ConversationsRequestBuilder", + "default": "undefined" + }, + "searchKeyword": { + "type": "string", + "default": "undefined" + }, + "activeConversation": { + "type": "CometChat.Conversation", + "default": "undefined" + }, + "lastMessageDateTimeFormat": { + "type": "CometChatDateFormatConfig", + "default": "hh:mm A today, Yesterday, dddd last week, DD/MM/YYYY older" + } + }, + "callbacks": { + "onItemClick": "(conversation: CometChat.Conversation) => void", + "onSelect": "(conversation: CometChat.Conversation, selected: boolean) => void", + "onError": "((error: CometChat.CometChatException) => void) | null", + "onEmpty": "() => void", + "onSearchBarClicked": "() => void" + }, + "visibility": { + "hideReceipts": { "type": "boolean", "default": false }, + "hideUserStatus": { "type": "boolean", "default": false }, + "hideGroupType": { "type": "boolean", "default": false }, + "hideUnreadCount": { "type": "boolean", "default": false }, + "hideDeleteConversation": { "type": "boolean", "default": false }, + "showSearchBar": { "type": "boolean", "default": true }, + "showScrollbar": { "type": "boolean", "default": false } + }, + "sound": { + "disableSoundForMessages": { "type": "boolean", "default": false }, + "customSoundForMessages": { "type": "string", "default": "built-in" } + }, + "selection": { + "selectionMode": { + "type": "CometChatConversationsSelectionMode", + "values": ["'none'", "'single'", "'multiple'"], + "default": "'none'" + } + }, + "viewSlots": { + "itemView": "(conversation: CometChat.Conversation) => ReactNode", + "leadingView": "(conversation: CometChat.Conversation) => ReactNode", + "titleView": "(conversation: CometChat.Conversation) => ReactNode", + "subtitleView": "(conversation: CometChat.Conversation) => ReactNode", + "trailingView": "(conversation: CometChat.Conversation) => ReactNode", + "headerView": "ReactNode", + "searchView": "ReactNode", + "loadingView": "ReactNode", + "emptyView": "ReactNode", + "errorView": "ReactNode", + "options": "(conversation: CometChat.Conversation) => CometChatConversationOption[]" + } + }, + "events": [ + { + "name": "ui:conversation/deleted", + "payload": "{ conversation: CometChat.Conversation }", + "description": "Conversation deleted from list" + } + ], + "sdkListeners": [ + "onTextMessageReceived", + "onMediaMessageReceived", + "onCustomMessageReceived", + "onInteractiveMessageReceived", + "onTypingStarted", + "onTypingEnded", + "onMessagesDelivered", + "onMessagesRead", + "onUserOnline", + "onUserOffline", + "onGroupMemberJoined", + "onGroupMemberLeft", + "onGroupMemberKicked", + "onGroupMemberBanned", + "onMemberAddedToGroup" + ], + "types": { + "CometChatDateFormatConfig": { + "today": "string | undefined", + "yesterday": "string | undefined", + "lastWeek": "string | undefined", + "otherDays": "string | undefined", + "relativeTime": { + "minute": "string | undefined", + "minutes": "string | undefined", + "hour": "string | undefined", + "hours": "string | undefined" + } + }, + "CometChatConversationOption": { + "id": "string", + "title": "string", + "iconURL": "string | undefined", + "onClick": "(conversation: CometChat.Conversation) => void" + }, + "CometChatConversationsSelectionMode": "'none' | 'single' | 'multiple'" + } +} +``` + + +## Overview + +`CometChatConversations` is a sidebar list component. It renders recent conversations for the logged-in user and emits the selected `CometChat.Conversation` via `onItemClick`. Wire it to `CometChatMessageHeader`, `CometChatMessageList`, and `CometChatMessageComposer` to build a standard two-panel chat layout. + +{/* TODO:IMAGE - CometChatConversations component showing a list of conversations with avatars, names, last messages, timestamps, and unread badges */} + + +**Live Preview** — interact with the default conversations list. + +[Open in Storybook ↗](https://storybook.cometchat.io/react/?path=/story/components-conversations-cometchat-conversations--default) + + + + +The component handles: +- Paginated fetching with infinite scroll +- Real-time updates (new messages, typing indicators, presence changes) +- Search filtering +- Swipe/hover options (delete conversation) +- Selection mode (single/multiple) + +--- + +## Usage + +### Flat API + +```tsx +import { CometChatConversations } from "@cometchat/chat-uikit-react"; + +function Sidebar() { + return ( + { + const entity = conversation.getConversationWith(); + // Pass entity to MessageHeader, MessageList, MessageComposer + }} + /> + ); +} +``` + +### Compound Composition + +```tsx +import { CometChatConversations } from "@cometchat/chat-uikit-react"; + +function Sidebar() { + return ( + + + + + + +

No conversations yet. Start a new chat!

+
+ +
+ ); +} +``` + +### Full Layout Example + +```tsx +import { useState } from "react"; +import { CometChat } from "@cometchat/chat-sdk-javascript"; +import { + CometChatConversations, + CometChatMessageHeader, + CometChatMessageList, + CometChatMessageComposer, +} from "@cometchat/chat-uikit-react"; + +function ChatApp() { + const [user, setUser] = useState(); + const [group, setGroup] = useState(); + + const handleConversationClick = (conversation: CometChat.Conversation) => { + const entity = conversation.getConversationWith(); + if (conversation.getConversationType() === "user") { + setUser(entity as CometChat.User); + setGroup(undefined); + } else { + setGroup(entity as CometChat.Group); + setUser(undefined); + } + }; + + return ( +
+
+ +
+
+ + + +
+
+ ); +} +``` + +--- + +## Filtering + +Pass a `CometChat.ConversationsRequestBuilder` to `conversationsRequestBuilder` to control which conversations load. Pass the builder instance — not the result of `.build()`. + +```tsx + +``` + +### Search + +The component includes a built-in search bar. When the user types, it filters conversations client-side by name. For server-side search, pass a `searchRequestBuilder`: + +```tsx + +``` + +To use the search bar as a trigger for a custom search UI (like `CometChatSearch`), pass `onSearchBarClicked`: + +```tsx + openGlobalSearch()} +/> +``` + +### Filter Recipes + +| Recipe | Code | +| --- | --- | +| Only 1-on-1 chats | `new CometChat.ConversationsRequestBuilder().setConversationType("user")` | +| Only group chats | `new CometChat.ConversationsRequestBuilder().setConversationType("group")` | +| Limit page size | `new CometChat.ConversationsRequestBuilder().setLimit(10)` | +| With tags | `new CometChat.ConversationsRequestBuilder().setTags(["support"])` | + +--- + +## Actions and Events + +### Callback Props + +| Prop | Signature | Fires when | +| --- | --- | --- | +| `onItemClick` | `(conversation: CometChat.Conversation) => void` | User clicks a conversation item | +| `onSelect` | `(conversation: CometChat.Conversation, selected: boolean) => void` | Conversation selected/deselected (selection mode) | +| `onError` | `((error: CometChat.CometChatException) => void) \| null` | SDK error occurs | +| `onEmpty` | `() => void` | List is empty after initial fetch | +| `onSearchBarClicked` | `() => void` | Search bar is clicked (makes input read-only) | + +### Events Emitted + +UI events this component publishes: + +| Event | Payload | Fires when | +| --- | --- | --- | +| `ui:conversation/deleted` | `{ conversation }` | User deletes a conversation | + +### Events Received + +UI events this component subscribes to (published by other components): + +| Event | Payload | Behavior | +| --- | --- | --- | +| `ui:message/sent` | `{ message, status }` | Moves conversation to top, updates last message, resets unread count | +| `ui:compose/edit` | `{ message, status }` | Updates the conversation's last message | +| `ui:message/deleted` | `{ message }` | Updates the conversation's last message | +| `ui:message/read` | `{ message }` | Resets unread count for that conversation | +| `ui:conversation/updated` | `{ conversation }` | Updates the conversation in the list | +| `ui:conversation/read` | `{ conversationId }` | Resets unread count by conversation ID | +| `ui:conversation/deleted` | `{ conversation }` | Removes the conversation from the list | +| `ui:group/created` | `{ group }` | Adds the new group conversation to the list | +| `ui:group/deleted` | `{ group }` | Removes the group conversation from the list | +| `ui:group/left` | `{ group }` | Removes the group conversation from the list | +| `ui:group/member-added` | `{ group, members, messages }` | Updates last message and moves to top | +| `ui:group/member-kicked` | `{ group, member, message }` | Updates last message and moves to top | +| `ui:group/member-banned` | `{ group, member, message }` | Updates last message and moves to top | +| `ui:group/member-unbanned` | `{ group, member, message }` | Updates last message and moves to top | + +### SDK Listeners (Automatic) + +These SDK listeners are attached internally. The component updates its state automatically — no manual subscription needed: + +- Message listeners: `onTextMessageReceived`, `onMediaMessageReceived`, `onCustomMessageReceived`, `onInteractiveMessageReceived` +- Typing: `onTypingStarted`, `onTypingEnded` +- Receipts: `onMessagesDelivered`, `onMessagesRead` +- Presence: `onUserOnline`, `onUserOffline` +- Groups: `onGroupMemberJoined`, `onGroupMemberLeft`, `onGroupMemberKicked`, `onGroupMemberBanned`, `onMemberAddedToGroup` + +--- + +## Customization + +### View Props + +Use view props to replace sections of the default UI while keeping the component's behavior intact: + +```tsx +} + itemView={(conversation) => } + emptyView={} + loadingView={} + errorView={} +/> +``` + +| Slot | Signature | Replaces | +| --- | --- | --- | +| `itemView` | `(conversation) => ReactNode` | Entire conversation row | +| `leadingView` | `(conversation) => ReactNode` | Avatar section | +| `titleView` | `(conversation) => ReactNode` | Conversation name | +| `subtitleView` | `(conversation) => ReactNode` | Last message preview | +| `trailingView` | `(conversation) => ReactNode` | Timestamp + unread badge | +| `headerView` | `ReactNode` | Header area | +| `searchView` | `ReactNode` | Search bar | +| `loadingView` | `ReactNode` | Loading shimmer | +| `emptyView` | `ReactNode` | Empty state | +| `errorView` | `ReactNode` | Error state | + +{/* TODO:IMAGE - Annotated diagram showing which view slot maps to which part of the conversation item */} + +### Compound Composition + +For full layout control, use sub-components. Omit any sub-component to hide it: + +```tsx + + {/* No Header or SearchBar — they won't render */} + + +``` + +Available sub-components: + +| Sub-component | Description | Props | Flat API equivalent | +| --- | --- | --- | --- | +| `Root` | Context provider and container | All Root props + `children` | — | +| `List` | Scrollable conversation list | `itemView`, `className` | `itemView` | +| `Item` | Individual conversation row | `leadingView`, `titleView`, `subtitleView`, `trailingView`, `className` | Per-item view props | +| `Header` | Header area | `title`, `children` | `headerView` | +| `SearchBar` | Search input | `placeholder`, `onClick` | `searchView` | +| `EmptyState` | Empty state | `children` | `emptyView` | +| `ErrorState` | Error state | `children` | `errorView` | +| `LoadingState` | Loading shimmer | `children` | `loadingView` | + +### CSS Styling + +Override design tokens on the component selector: + +```css +.cometchat-conversations { + --cometchat-background-color-01: #1a1a2e; + --cometchat-text-color-primary: #ffffff; +} + +.cometchat-conversations__item--active { + background: var(--cometchat-primary-color); +} +``` + +--- + +## Props + +All props are optional. + + +View slot props (`headerView`, `searchView`, `loadingView`, `emptyView`, `errorView`, `itemView`, `leadingView`, `titleView`, `subtitleView`, `trailingView`) are convenience props available only on the flat API. In compound composition mode, use the corresponding sub-components directly. + + +--- + +### conversationsRequestBuilder + +Custom request builder for fetching conversations. Controls pagination, filtering, and sorting. + +| | | +| --- | --- | +| Type | `CometChat.ConversationsRequestBuilder` | +| Default | SDK default (limit 30) | + +--- + +### searchRequestBuilder + +Custom request builder used specifically when the user searches. Separate from the main builder. + +| | | +| --- | --- | +| Type | `CometChat.ConversationsRequestBuilder` | +| Default | `undefined` | + +--- + +### searchKeyword + +Initial search keyword to pre-filter conversations on mount. + +| | | +| --- | --- | +| Type | `string` | +| Default | `undefined` | + +--- + +### activeConversation + +The currently active/highlighted conversation. The matching item receives an active visual state. + +| | | +| --- | --- | +| Type | `CometChat.Conversation` | +| Default | `undefined` | + +--- + +### lastMessageDateTimeFormat + +Custom date/time format for the last message timestamp shown in each conversation item. + +| | | +| --- | --- | +| Type | `CometChatDateFormatConfig` | +| Default | `{ today: 'hh:mm A', yesterday: 'Yesterday', lastWeek: 'dddd', otherDays: 'DD/MM/YYYY' }` | + +--- + +### hideReceipts + +Hide message delivery/read receipts (double ticks) on conversation items. + +| | | +| --- | --- | +| Type | `boolean` | +| Default | `false` | + +--- + +### hideUserStatus + +Hide the online/offline status indicator on user avatars. + +| | | +| --- | --- | +| Type | `boolean` | +| Default | `false` | + +--- + +### hideGroupType + +Hide the group type indicator (public/private/password) on group conversation items. + +| | | +| --- | --- | +| Type | `boolean` | +| Default | `false` | + +--- + +### hideUnreadCount + +Hide the unread message count badge. + +| | | +| --- | --- | +| Type | `boolean` | +| Default | `false` | + +--- + +### hideDeleteConversation + +Hide the delete option in the conversation item's context menu. + +| | | +| --- | --- | +| Type | `boolean` | +| Default | `false` | + +--- + +### showSearchBar + +Whether to show the search bar. Set to `false` to hide it entirely. + +| | | +| --- | --- | +| Type | `boolean` | +| Default | `true` | + +--- + +### showScrollbar + +Show the native scrollbar on the conversation list. + +| | | +| --- | --- | +| Type | `boolean` | +| Default | `false` | + +--- + +### selectionMode + +Enable selection mode for multi-select operations. + +| | | +| --- | --- | +| Type | `'none' \| 'single' \| 'multiple'` | +| Default | `'none'` | + +--- + +### disableSoundForMessages + +Disable the notification sound when new messages arrive. + +| | | +| --- | --- | +| Type | `boolean` | +| Default | `false` | + +--- + +### customSoundForMessages + +Custom sound URL to play when new messages arrive (replaces the built-in sound). + +| | | +| --- | --- | +| Type | `string` | +| Default | Built-in notification sound | + +--- + +### options + +Function that returns context menu options for each conversation item (shown on hover/swipe). + +| | | +| --- | --- | +| Type | `(conversation: CometChat.Conversation) => CometChatConversationOption[]` | +| Default | Default options (delete) | + +```tsx + [ + { + id: "pin", + title: "Pin", + iconURL: pinIcon, + onClick: (conv) => pinConversation(conv), + }, + { + id: "mute", + title: "Mute", + iconURL: muteIcon, + onClick: (conv) => muteConversation(conv), + }, + ]} +/> +``` + +--- + +### onItemClick + +Callback when a conversation item is clicked. + +| | | +| --- | --- | +| Type | `(conversation: CometChat.Conversation) => void` | +| Default | `undefined` | + +--- + +### onSelect + +Callback when a conversation is selected or deselected (only fires in selection mode). + +| | | +| --- | --- | +| Type | `(conversation: CometChat.Conversation, selected: boolean) => void` | +| Default | `undefined` | + +--- + +### onError + +Callback when an SDK error occurs during fetch or real-time operations. + +| | | +| --- | --- | +| Type | `((error: CometChat.CometChatException) => void) \| null` | +| Default | `null` | + +--- + +### onEmpty + +Callback when the conversation list is empty after the initial fetch completes. + +| | | +| --- | --- | +| Type | `() => void` | +| Default | `undefined` | + +--- + +### onSearchBarClicked + +Callback when the search bar is clicked. When provided, the search input becomes read-only and acts as a trigger (useful for opening a global search component like `CometChatSearch`). + +| | | +| --- | --- | +| Type | `() => void` | +| Default | `undefined` | + +--- + +## CSS Selectors + +| Target | Selector | +| --- | --- | +| Root container | `.cometchat-conversations` | +| Header | `.cometchat-conversations__header` | +| Search bar | `.cometchat-conversations__search-bar` | +| List container | `.cometchat-conversations__list` | +| Conversation item | `.cometchat-conversations__item` | +| Active item | `.cometchat-conversations__item--active` | +| Item avatar | `.cometchat-conversations__item-avatar` | +| Item title | `.cometchat-conversations__item-title` | +| Item subtitle | `.cometchat-conversations__item-subtitle` | +| Item trailing | `.cometchat-conversations__item-trailing` | +| Unread badge | `.cometchat-conversations__item-unread-count` | +| Empty state | `.cometchat-conversations__empty-state` | +| Error state | `.cometchat-conversations__error-state` | +| Loading state | `.cometchat-conversations__loading-state` | + +--- + +## Next Steps + + + + Browse and select users for new conversations + + + Display messages for the selected conversation + + + Search across conversations and messages + + + Customize colors, fonts, and spacing + + diff --git a/ui-kit/react/components/create-poll.mdx b/ui-kit/react/components/create-poll.mdx new file mode 100644 index 000000000..8fea9c707 --- /dev/null +++ b/ui-kit/react/components/create-poll.mdx @@ -0,0 +1,254 @@ +--- +title: "Create Poll" +description: "A modal form for creating poll messages with dynamic answer options, validation, and reply-to-message support." +--- + + +```json +{ + "component": "CometChatCreatePoll", + "package": "@cometchat/chat-uikit-react", + "import": "import { CometChatCreatePoll } from \"@cometchat/chat-uikit-react\";", + "description": "Modal form for creating poll messages with question, dynamic options, and validation.", + "cssRootClass": ".cometchat-create-poll", + "props": { + "data": { + "user": { "type": "CometChat.User", "default": "undefined" }, + "group": { "type": "CometChat.Group", "default": "undefined" }, + "replyToMessage": { "type": "CometChat.BaseMessage", "default": "undefined" } + }, + "behavior": { + "defaultAnswers": { "type": "number", "default": "2" } + }, + "callbacks": { + "onClose": { "type": "() => void", "default": "undefined" }, + "onPollCreated": { "type": "() => void", "default": "undefined" }, + "onError": { "type": "(error: unknown) => void", "default": "undefined" } + }, + "text": { + "title": { "type": "string", "default": "localized 'Create Poll'" }, + "questionPlaceholderText": { "type": "string", "default": "localized placeholder" }, + "answerPlaceholderText": { "type": "string", "default": "localized placeholder" }, + "answerHelpText": { "type": "string", "default": "localized help text" }, + "addAnswerText": { "type": "string", "default": "localized 'Add Option'" }, + "createPollButtonText": { "type": "string", "default": "localized 'Create'" } + } + } +} +``` + + +## Where It Fits + +`CometChatCreatePoll` is a modal dialog opened from the message composer's attachment menu when the Polls plugin is registered. It creates a poll via `CometChat.callExtension('polls', 'POST', 'v2/create', payload)`. + +```tsx lines +import { useState } from "react"; +import { CometChatCreatePoll } from "@cometchat/chat-uikit-react"; +import "@cometchat/chat-uikit-react/css-variables.css"; + +function ChatComposer({ user }) { + const [showPoll, setShowPoll] = useState(false); + return ( + <> + + {showPoll && ( +
+ setShowPoll(false)} + onPollCreated={() => setShowPoll(false)} + /> +
+ )} + + ); +} +``` + +## Minimal Render + +```tsx lines +import { CometChatCreatePoll } from "@cometchat/chat-uikit-react"; +import "@cometchat/chat-uikit-react/css-variables.css"; + +function Demo() { + return {}} />; +} +``` + +Root CSS class: `.cometchat-create-poll` + +## Features + +- Question input with placeholder text +- Dynamic answer options (add/remove, minimum 2, maximum 12) +- Validation: requires non-empty question and at least 2 non-empty options +- Loading state on the create button during API call +- Error display with `role="alert"` +- Reply-to-message support via `quotedMessageId` +- Escape key closes the dialog +- Focus restoration on unmount +- `role="dialog"`, `aria-modal="true"`, `aria-labelledby` + +## Props + +All props are optional unless noted otherwise. + +--- + +### user + +User to send the poll to (for 1:1 conversations). + +| | | +| --- | --- | +| Type | `CometChat.User` | +| Default | `undefined` | + +--- + +### group + +Group to send the poll to (for group conversations). + +| | | +| --- | --- | +| Type | `CometChat.Group` | +| Default | `undefined` | + +--- + +### replyToMessage + +Message to reply to (for quoted replies). When provided, the poll is sent as a reply to this message. + +| | | +| --- | --- | +| Type | `CometChat.BaseMessage` | +| Default | `undefined` | + +--- + +### defaultAnswers + +Default number of answer option inputs. Minimum 2, maximum 12. + +| | | +| --- | --- | +| Type | `number` | +| Default | `2` | + +--- + +### onClose + +Callback when close is requested (close button or Escape key). + +| | | +| --- | --- | +| Type | `() => void` | +| Default | `undefined` | + +--- + +### onPollCreated + +Callback when the poll is created successfully. + +| | | +| --- | --- | +| Type | `() => void` | +| Default | `undefined` | + +--- + +### onError + +Callback when an error occurs during poll creation. + +| | | +| --- | --- | +| Type | `(error: unknown) => void` | +| Default | `undefined` | + +--- + +### title + +Override for the dialog title text. + +| | | +| --- | --- | +| Type | `string` | +| Default | Localized `"Create Poll"` | + +--- + +### questionPlaceholderText + +Placeholder text for the question input field. + +| | | +| --- | --- | +| Type | `string` | +| Default | Localized placeholder | + +--- + +### answerPlaceholderText + +Placeholder text for answer option input fields. + +| | | +| --- | --- | +| Type | `string` | +| Default | Localized placeholder | + +--- + +### answerHelpText + +Help text displayed below the answer options section. + +| | | +| --- | --- | +| Type | `string` | +| Default | Localized help text | + +--- + +### addAnswerText + +Text for the "Add Option" button. + +| | | +| --- | --- | +| Type | `string` | +| Default | Localized `"Add Option"` | + +--- + +### createPollButtonText + +Text for the "Create" submit button. + +| | | +| --- | --- | +| Type | `string` | +| Default | Localized `"Create"` | + +## CSS Selectors + +| Target | Selector | +| --- | --- | +| Root | `.cometchat-create-poll` | +| Header | `.cometchat-create-poll__header` | +| Title | `.cometchat-create-poll__header-title` | +| Close button | `.cometchat-create-poll__header-close` | +| Question input | `.cometchat-create-poll__question-input` | +| Option input | `.cometchat-create-poll__option-input` | +| Remove button | `.cometchat-create-poll__option-remove` | +| Add button | `.cometchat-create-poll__add-button` | +| Create button | `.cometchat-create-poll__create-button` | +| Error message | `.cometchat-create-poll__error` | diff --git a/ui-kit/react/components/date.mdx b/ui-kit/react/components/date.mdx new file mode 100644 index 000000000..a1b9103bd --- /dev/null +++ b/ui-kit/react/components/date.mdx @@ -0,0 +1,394 @@ +--- +title: "Date" +description: "A composable date/time display component that formats Unix timestamps based on temporal proximity — today, yesterday, last week, or older." +--- + + +```json +{ + "component": "CometChatDate", + "package": "@cometchat/chat-uikit-react", + "import": "import { CometChatDate } from \"@cometchat/chat-uikit-react\";", + "cssImport": "import \"@cometchat/chat-uikit-react/css-variables.css\";", + "description": "A composable date/time display component that formats Unix timestamps based on temporal proximity — today, yesterday, last week, or older.", + "cssRootClass": ".cometchat-date", + "subComponents": ["Root", "Text"], + "props": { + "Root": { + "timestamp": { "type": "number", "default": "undefined", "note": "Required. Unix timestamp in seconds." }, + "formatConfig": { "type": "CometChatDateFormatConfig", "default": "{ today: 'hh:mm A', yesterday: 'Yesterday', lastWeek: 'dddd', otherDays: 'DD/MM/YYYY' }" }, + "formatter": { "type": "(timestamp: number) => string", "default": "undefined" }, + "variant": { "type": "'caption' | 'caption2' | 'body' | 'label' | 'separator'", "default": "'caption'" }, + "className": { "type": "string", "default": "undefined" }, + "children": { "type": "ReactNode", "default": "undefined" } + }, + "Text": { + "className": { "type": "string", "default": "undefined" } + } + }, + "types": { + "CometChatDateFormatConfig": { + "today": "string | undefined", + "yesterday": "string | undefined", + "lastWeek": "string | undefined", + "otherDays": "string | undefined", + "relativeTime": "{ minute?: string; minutes?: string; hour?: string; hours?: string } | undefined" + }, + "CometChatDateVariant": "'caption' | 'caption2' | 'body' | 'label' | 'separator'", + "CometChatDateContextValue": { + "timestamp": "number", + "formattedDate": "string", + "isoDate": "string", + "fullDateLabel": "string", + "variant": "CometChatDateVariant" + } + } +} +``` + + +## Where It Fits + +`CometChatDate` is a base component used wherever a formatted date or time needs to be displayed. It appears in conversation list trailing dates, message list date separators, sticky date headers, message information receipts, thread headers, call logs, and search results. It renders a semantic `