@cometchat/skills 3.0.0 → 4.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (101) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +44 -17
  3. package/bin/install.js +389 -43
  4. package/package.json +19 -9
  5. package/skills/cometchat/SKILL.md +1066 -265
  6. package/skills/cometchat-android-v5/SKILL.md +120 -0
  7. package/skills/cometchat-android-v5-components/SKILL.md +430 -0
  8. package/skills/cometchat-android-v5-core/SKILL.md +468 -0
  9. package/skills/cometchat-android-v5-customization/SKILL.md +305 -0
  10. package/skills/cometchat-android-v5-extensions/SKILL.md +124 -0
  11. package/skills/cometchat-android-v5-features/SKILL.md +130 -0
  12. package/skills/cometchat-android-v5-placement/SKILL.md +276 -0
  13. package/skills/cometchat-android-v5-production/SKILL.md +94 -0
  14. package/skills/cometchat-android-v5-push/SKILL.md +620 -0
  15. package/skills/cometchat-android-v5-testing/SKILL.md +187 -0
  16. package/skills/cometchat-android-v5-theming/SKILL.md +166 -0
  17. package/skills/cometchat-android-v5-troubleshooting/SKILL.md +73 -0
  18. package/skills/cometchat-android-v6/SKILL.md +107 -0
  19. package/skills/cometchat-android-v6-builder-settings/SKILL.md +145 -0
  20. package/skills/cometchat-android-v6-compose-components/SKILL.md +202 -0
  21. package/skills/cometchat-android-v6-compose-customization/SKILL.md +280 -0
  22. package/skills/cometchat-android-v6-compose-placement/SKILL.md +213 -0
  23. package/skills/cometchat-android-v6-compose-theming/SKILL.md +224 -0
  24. package/skills/cometchat-android-v6-core/SKILL.md +354 -0
  25. package/skills/cometchat-android-v6-events/SKILL.md +212 -0
  26. package/skills/cometchat-android-v6-extensions/SKILL.md +191 -0
  27. package/skills/cometchat-android-v6-features/SKILL.md +130 -0
  28. package/skills/cometchat-android-v6-kotlin-components/SKILL.md +197 -0
  29. package/skills/cometchat-android-v6-kotlin-customization/SKILL.md +268 -0
  30. package/skills/cometchat-android-v6-kotlin-placement/SKILL.md +248 -0
  31. package/skills/cometchat-android-v6-kotlin-theming/SKILL.md +202 -0
  32. package/skills/cometchat-android-v6-production/SKILL.md +187 -0
  33. package/skills/cometchat-android-v6-push/SKILL.md +274 -0
  34. package/skills/cometchat-android-v6-testing/SKILL.md +279 -0
  35. package/skills/cometchat-android-v6-troubleshooting/SKILL.md +249 -0
  36. package/skills/cometchat-angular-components/SKILL.md +706 -0
  37. package/skills/cometchat-angular-core/SKILL.md +444 -0
  38. package/skills/cometchat-angular-customization/SKILL.md +424 -0
  39. package/skills/cometchat-angular-features/SKILL.md +447 -0
  40. package/skills/cometchat-angular-patterns/SKILL.md +447 -0
  41. package/skills/cometchat-angular-placement/SKILL.md +685 -0
  42. package/skills/cometchat-angular-production/SKILL.md +415 -0
  43. package/skills/cometchat-angular-theming/SKILL.md +365 -0
  44. package/skills/cometchat-angular-troubleshooting/SKILL.md +329 -0
  45. package/skills/cometchat-astro-patterns/SKILL.md +3 -3
  46. package/skills/cometchat-components/SKILL.md +11 -0
  47. package/skills/cometchat-core/SKILL.md +11 -6
  48. package/skills/cometchat-customization/references/component-catalog.md +1 -1
  49. package/skills/cometchat-features/SKILL.md +176 -108
  50. package/skills/cometchat-flutter-v5/SKILL.md +167 -0
  51. package/skills/cometchat-flutter-v5-calls/SKILL.md +192 -0
  52. package/skills/cometchat-flutter-v5-conversations/SKILL.md +117 -0
  53. package/skills/cometchat-flutter-v5-core/SKILL.md +221 -0
  54. package/skills/cometchat-flutter-v5-customization/SKILL.md +227 -0
  55. package/skills/cometchat-flutter-v5-events/SKILL.md +155 -0
  56. package/skills/cometchat-flutter-v5-messages/SKILL.md +258 -0
  57. package/skills/cometchat-flutter-v5-production/SKILL.md +207 -0
  58. package/skills/cometchat-flutter-v5-push/SKILL.md +284 -0
  59. package/skills/cometchat-flutter-v5-theming/SKILL.md +160 -0
  60. package/skills/cometchat-flutter-v5-troubleshooting/SKILL.md +129 -0
  61. package/skills/cometchat-flutter-v5-users-groups/SKILL.md +151 -0
  62. package/skills/cometchat-flutter-v6/SKILL.md +445 -0
  63. package/skills/cometchat-flutter-v6-calls/SKILL.md +333 -0
  64. package/skills/cometchat-flutter-v6-components/SKILL.md +365 -0
  65. package/skills/cometchat-flutter-v6-conversations/SKILL.md +210 -0
  66. package/skills/cometchat-flutter-v6-core/SKILL.md +305 -0
  67. package/skills/cometchat-flutter-v6-customization/SKILL.md +666 -0
  68. package/skills/cometchat-flutter-v6-events/SKILL.md +216 -0
  69. package/skills/cometchat-flutter-v6-features/SKILL.md +406 -0
  70. package/skills/cometchat-flutter-v6-messages/SKILL.md +333 -0
  71. package/skills/cometchat-flutter-v6-migration/SKILL.md +381 -0
  72. package/skills/cometchat-flutter-v6-placement/SKILL.md +398 -0
  73. package/skills/cometchat-flutter-v6-production/SKILL.md +632 -0
  74. package/skills/cometchat-flutter-v6-theming/SKILL.md +260 -0
  75. package/skills/cometchat-flutter-v6-troubleshooting/SKILL.md +726 -0
  76. package/skills/cometchat-flutter-v6-users-groups/SKILL.md +216 -0
  77. package/skills/cometchat-ios/SKILL.md +323 -0
  78. package/skills/cometchat-ios-components/SKILL.md +651 -0
  79. package/skills/cometchat-ios-core/SKILL.md +822 -0
  80. package/skills/cometchat-ios-customization/SKILL.md +825 -0
  81. package/skills/cometchat-ios-features/SKILL.md +725 -0
  82. package/skills/cometchat-ios-placement/SKILL.md +750 -0
  83. package/skills/cometchat-ios-production/SKILL.md +730 -0
  84. package/skills/cometchat-ios-push/SKILL.md +582 -0
  85. package/skills/cometchat-ios-theming/SKILL.md +631 -0
  86. package/skills/cometchat-ios-troubleshooting/SKILL.md +983 -0
  87. package/skills/cometchat-native-bare-patterns/SKILL.md +470 -0
  88. package/skills/cometchat-native-components/SKILL.md +594 -0
  89. package/skills/cometchat-native-core/SKILL.md +407 -0
  90. package/skills/cometchat-native-customization/SKILL.md +594 -0
  91. package/skills/cometchat-native-expo-patterns/SKILL.md +485 -0
  92. package/skills/cometchat-native-features/SKILL.md +608 -0
  93. package/skills/cometchat-native-placement/SKILL.md +500 -0
  94. package/skills/cometchat-native-production/SKILL.md +694 -0
  95. package/skills/cometchat-native-push/SKILL.md +593 -0
  96. package/skills/cometchat-native-testing/SKILL.md +583 -0
  97. package/skills/cometchat-native-theming/SKILL.md +656 -0
  98. package/skills/cometchat-native-troubleshooting/SKILL.md +433 -0
  99. package/skills/cometchat-nextjs-patterns/SKILL.md +5 -5
  100. package/skills/cometchat-production/SKILL.md +60 -0
  101. package/skills/cometchat-react-router-patterns/SKILL.md +23 -21
@@ -0,0 +1,685 @@
1
+ ---
2
+ name: cometchat-angular-placement
3
+ description: "Where to put chat in an Angular app — Route-based, Sidebar, Modal/Dialog, Tab-based, and Embedded placements. Maps each to CometChat component composition with Angular Router wiring and layout patterns."
4
+ license: "MIT"
5
+ compatibility: "Angular >=12 <=15; @cometchat/chat-uikit-angular ^4; @cometchat/chat-sdk-javascript ^4"
6
+ allowed-tools: "executeBash, readFile, fileSearch, listDirectory, AskUserQuestion"
7
+ metadata:
8
+ author: "CometChat"
9
+ version: "3.0.0"
10
+ tags: "cometchat angular placement routing sidebar modal tabs embedded layout"
11
+ ---
12
+
13
+ ## Purpose
14
+
15
+ Teaches Claude the five canonical placement patterns for putting chat inside an Angular app. Each pattern specifies:
16
+
17
+ 1. Which CometChat components to compose
18
+ 2. How to wire the placement into Angular Router or Angular Material
19
+ 3. Layout gotchas (flex containers, height constraints, z-index)
20
+ 4. When to choose this placement over the alternatives
21
+
22
+ **Read `cometchat-angular-core` and `cometchat-angular-components` before this skill** — the init/login lifecycle and component catalog are prerequisites.
23
+
24
+ Ground truth: `docs/ui-kit/angular/getting-started`, `docs/ui-kit/angular/multi-tab-chat-ui-guide`, and `@cometchat/chat-uikit-angular@4.x` composite components.
25
+
26
+ ---
27
+
28
+ ## "What are you building?" — placement recommendation
29
+
30
+ | User intent | Recommended placement | Experience |
31
+ |---|---|---|
32
+ | Messaging app (WhatsApp / Telegram style) | **Route-based** — `/conversations` → `/messages/:uid` | Full-page chat inside the app |
33
+ | SaaS / marketplace with chat as a feature | **Sidebar** — persistent chat panel alongside main content | Split-pane layout |
34
+ | Support app or focused 1-to-1 | **Route-based (single thread)** — no conversation list, go straight into one chat | Single thread |
35
+ | Full messaging hub with calls / users / groups | **Tab-based** — Chats / Users / Groups / Calls tabs | Tab-based messenger |
36
+ | Occasional chat overlay from a non-chat screen | **Modal/Dialog** — Angular Material `MatDialog` or CDK overlay | Modal |
37
+ | Chat embedded inside an existing page section | **Embedded** — CometChat components inside a parent layout | Inline |
38
+
39
+ ---
40
+
41
+ ## Visual reference — five Angular placement patterns
42
+
43
+ ### 1. Route-based (full page)
44
+
45
+ ```
46
+ ┌─────────────────────────────────────────┐
47
+ │ ← Hiking Group ⋮ │ ← cometchat-message-header
48
+ ├─────────────────────────────────────────┤
49
+ │ │
50
+ │ (messages) │ ← cometchat-message-list
51
+ │ │
52
+ ├─────────────────────────────────────────┤
53
+ │ + Type a message... ▶ │ ← cometchat-message-composer
54
+ └─────────────────────────────────────────┘
55
+ ```
56
+
57
+ ### 2. Sidebar (split-pane)
58
+
59
+ ```
60
+ ┌──────────────┬──────────────────────────┐
61
+ │ Conversations│ ← Hiking Group ⋮ │
62
+ │ ─────────────│ ─────────────────────────│
63
+ │ Hiking Group │ │
64
+ │ Alice │ (messages) │
65
+ │ Bob │ │
66
+ │ │ ─────────────────────────│
67
+ │ │ Type a message... ▶ │
68
+ └──────────────┴──────────────────────────┘
69
+ ```
70
+
71
+ ### 3. Modal/Dialog
72
+
73
+ ```
74
+ ┌──────────────────────┐
75
+ │ Chat with Alice ✕ │
76
+ ├──────────────────────┤
77
+ │ │
78
+ │ (messages) │
79
+ │ │
80
+ ├──────────────────────┤
81
+ │ Type message... ▶ │
82
+ └──────────────────────┘
83
+ (page content dimmed behind)
84
+ ```
85
+
86
+ ### 4. Tab-based
87
+
88
+ ```
89
+ ┌─────────────────────────────────────────┐
90
+ │ Chats Users Groups Calls │ ← tab bar
91
+ ├─────────────────────────────────────────┤
92
+ │ │
93
+ │ (active tab content) │
94
+ │ │
95
+ └─────────────────────────────────────────┘
96
+ ```
97
+
98
+ ### 5. Embedded (inside an existing page)
99
+
100
+ ```
101
+ ┌─────────────────────────────────────────┐
102
+ │ Product details │
103
+ │ [product image + specs] │
104
+ ├─────────────────────────────────────────┤
105
+ │ Chat with seller │
106
+ │ ┌─────────────────────────────────────┐ │
107
+ │ │ cometchat-message-header │ │
108
+ │ │ cometchat-message-list │ │ ← embedded chat
109
+ │ │ cometchat-message-composer │ │
110
+ │ └─────────────────────────────────────┘ │
111
+ └─────────────────────────────────────────┘
112
+ ```
113
+
114
+ ---
115
+
116
+ ## 1. Route-based placement
117
+
118
+ The most common pattern — chat lives in its own route, navigated via Angular Router.
119
+
120
+ ### Pattern A — Conversations list → Messages (two routes)
121
+
122
+ ```typescript
123
+ // app-routing.module.ts
124
+ import { Routes } from "@angular/router";
125
+ import { ConversationsComponent } from "./conversations/conversations.component";
126
+ import { MessagesComponent } from "./messages/messages.component";
127
+
128
+ export const routes: Routes = [
129
+ { path: "conversations", component: ConversationsComponent },
130
+ { path: "messages/user/:uid", component: MessagesComponent },
131
+ { path: "messages/group/:guid", component: MessagesComponent },
132
+ { path: "", redirectTo: "conversations", pathMatch: "full" },
133
+ ];
134
+ ```
135
+
136
+ ```typescript
137
+ // conversations.component.ts
138
+ import { Component } from "@angular/core";
139
+ import { Router } from "@angular/router";
140
+ import { CometChat } from "@cometchat/chat-sdk-javascript";
141
+ import { CometChatConversations } from "@cometchat/chat-uikit-angular";
142
+ import { CUSTOM_ELEMENTS_SCHEMA } from "@angular/core";
143
+
144
+ @Component({
145
+ selector: "app-conversations",
146
+ standalone: true,
147
+ imports: [CometChatConversations],
148
+ schemas: [CUSTOM_ELEMENTS_SCHEMA],
149
+ template: `
150
+ <div style="height: 100vh; display: flex; flex-direction: column;">
151
+ <cometchat-conversations
152
+ [onItemClick]="handleConvClick"
153
+ style="flex: 1; overflow: hidden;"
154
+ ></cometchat-conversations>
155
+ </div>
156
+ `,
157
+ })
158
+ export class ConversationsComponent {
159
+ constructor(private router: Router) {}
160
+
161
+ handleConvClick = (conversation: CometChat.Conversation): void => {
162
+ const entity = conversation.getConversationWith();
163
+ const type = conversation.getConversationType();
164
+ if (type === "user") {
165
+ this.router.navigate(["/messages/user", (entity as CometChat.User).getUid()]);
166
+ } else {
167
+ this.router.navigate(["/messages/group", (entity as CometChat.Group).getGuid()]);
168
+ }
169
+ };
170
+ }
171
+ ```
172
+
173
+ ```typescript
174
+ // messages.component.ts
175
+ import { Component, OnInit } from "@angular/core";
176
+ import { ActivatedRoute, Router } from "@angular/router";
177
+ import { CometChat } from "@cometchat/chat-sdk-javascript";
178
+ import {
179
+ CometChatMessageHeader,
180
+ CometChatMessageList,
181
+ CometChatMessageComposer,
182
+ } from "@cometchat/chat-uikit-angular";
183
+ import { CommonModule } from "@angular/common";
184
+ import { CUSTOM_ELEMENTS_SCHEMA } from "@angular/core";
185
+
186
+ @Component({
187
+ selector: "app-messages",
188
+ standalone: true,
189
+ imports: [CommonModule, CometChatMessageHeader, CometChatMessageList, CometChatMessageComposer],
190
+ schemas: [CUSTOM_ELEMENTS_SCHEMA],
191
+ template: `
192
+ <div style="height: 100vh; display: flex; flex-direction: column;">
193
+ <cometchat-message-header
194
+ [user]="selectedUser"
195
+ [group]="selectedGroup"
196
+ [onBack]="goBack"
197
+ [hideBackButton]="false"
198
+ ></cometchat-message-header>
199
+ <cometchat-message-list
200
+ [user]="selectedUser"
201
+ [group]="selectedGroup"
202
+ style="flex: 1; overflow: hidden;"
203
+ ></cometchat-message-list>
204
+ <cometchat-message-composer
205
+ [user]="selectedUser"
206
+ [group]="selectedGroup"
207
+ ></cometchat-message-composer>
208
+ </div>
209
+ `,
210
+ })
211
+ export class MessagesComponent implements OnInit {
212
+ selectedUser: CometChat.User | undefined;
213
+ selectedGroup: CometChat.Group | undefined;
214
+
215
+ constructor(private route: ActivatedRoute, private router: Router) {}
216
+
217
+ ngOnInit(): void {
218
+ const uid = this.route.snapshot.paramMap.get("uid");
219
+ const guid = this.route.snapshot.paramMap.get("guid");
220
+
221
+ if (uid) {
222
+ CometChat.getUser(uid).then((user) => (this.selectedUser = user));
223
+ } else if (guid) {
224
+ CometChat.getGroup(guid).then((group) => (this.selectedGroup = group));
225
+ }
226
+ }
227
+
228
+ goBack = (): void => {
229
+ this.router.navigate(["/conversations"]);
230
+ };
231
+ }
232
+ ```
233
+
234
+ ### Pattern B — Single thread (no conversation list)
235
+
236
+ For support chat, marketplace "Contact seller", or any focused 1-to-1 where the target is known in advance.
237
+
238
+ ```typescript
239
+ // support-chat.component.ts
240
+ @Component({
241
+ selector: "app-support-chat",
242
+ standalone: true,
243
+ imports: [CommonModule, CometChatMessageHeader, CometChatMessageList, CometChatMessageComposer],
244
+ schemas: [CUSTOM_ELEMENTS_SCHEMA],
245
+ template: `
246
+ <div *ngIf="agent; else loading" style="height: 100vh; display: flex; flex-direction: column;">
247
+ <cometchat-message-header [user]="agent"></cometchat-message-header>
248
+ <cometchat-message-list
249
+ [user]="agent"
250
+ style="flex: 1; overflow: hidden;"
251
+ ></cometchat-message-list>
252
+ <cometchat-message-composer [user]="agent"></cometchat-message-composer>
253
+ </div>
254
+ <ng-template #loading><p>Connecting to support...</p></ng-template>
255
+ `,
256
+ })
257
+ export class SupportChatComponent implements OnInit {
258
+ agent: CometChat.User | undefined;
259
+
260
+ ngOnInit(): void {
261
+ CometChat.getUser("support-agent-uid").then((user) => (this.agent = user));
262
+ }
263
+ }
264
+ ```
265
+
266
+ ---
267
+
268
+ ## 2. Sidebar placement (split-pane)
269
+
270
+ For SaaS apps where chat is a persistent panel alongside main content.
271
+
272
+ ```typescript
273
+ // chat-layout.component.ts
274
+ @Component({
275
+ selector: "app-chat-layout",
276
+ standalone: true,
277
+ imports: [
278
+ CommonModule,
279
+ CometChatConversations,
280
+ CometChatMessageHeader,
281
+ CometChatMessageList,
282
+ CometChatMessageComposer,
283
+ ],
284
+ schemas: [CUSTOM_ELEMENTS_SCHEMA],
285
+ template: `
286
+ <div style="display: flex; height: 100vh; overflow: hidden;">
287
+ <!-- Sidebar: conversation list -->
288
+ <div style="width: 320px; flex-shrink: 0; border-right: 1px solid #e8e8e8; overflow: hidden;">
289
+ <cometchat-conversations
290
+ [onItemClick]="handleConvClick"
291
+ [activeConversation]="activeConversation"
292
+ style="height: 100%;"
293
+ ></cometchat-conversations>
294
+ </div>
295
+
296
+ <!-- Main: message thread -->
297
+ <div style="flex: 1; display: flex; flex-direction: column; overflow: hidden;">
298
+ <ng-container *ngIf="selectedUser || selectedGroup; else placeholder">
299
+ <cometchat-message-header
300
+ [user]="selectedUser"
301
+ [group]="selectedGroup"
302
+ [hideBackButton]="true"
303
+ ></cometchat-message-header>
304
+ <cometchat-message-list
305
+ [user]="selectedUser"
306
+ [group]="selectedGroup"
307
+ style="flex: 1; overflow: hidden;"
308
+ ></cometchat-message-list>
309
+ <cometchat-message-composer
310
+ [user]="selectedUser"
311
+ [group]="selectedGroup"
312
+ ></cometchat-message-composer>
313
+ </ng-container>
314
+ <ng-template #placeholder>
315
+ <div style="flex: 1; display: flex; align-items: center; justify-content: center; color: #727272;">
316
+ Select a conversation to start chatting
317
+ </div>
318
+ </ng-template>
319
+ </div>
320
+ </div>
321
+ `,
322
+ })
323
+ export class ChatLayoutComponent {
324
+ selectedUser: CometChat.User | undefined;
325
+ selectedGroup: CometChat.Group | undefined;
326
+ activeConversation: CometChat.Conversation | undefined;
327
+
328
+ handleConvClick = (conversation: CometChat.Conversation): void => {
329
+ this.activeConversation = conversation;
330
+ const entity = conversation.getConversationWith();
331
+ if (entity instanceof CometChat.User) {
332
+ this.selectedUser = entity;
333
+ this.selectedGroup = undefined;
334
+ } else {
335
+ this.selectedGroup = entity as CometChat.Group;
336
+ this.selectedUser = undefined;
337
+ }
338
+ };
339
+ }
340
+ ```
341
+
342
+ ### Sidebar layout notes
343
+
344
+ - The sidebar container needs `overflow: hidden` — `<cometchat-conversations>` fills 100% of its parent.
345
+ - The message area needs `flex: 1; overflow: hidden` so the list fills the remaining space.
346
+ - Pass `[activeConversation]` to `<cometchat-conversations>` to highlight the selected row.
347
+ - `[hideBackButton]="true"` on the header since there's no navigation to go back to.
348
+
349
+ ---
350
+
351
+ ## 3. Modal/Dialog placement
352
+
353
+ For occasional chat that doesn't belong in the primary navigation. Use Angular Material `MatDialog` or Angular CDK overlay.
354
+
355
+ ### ⚠️ Critical — never use `<cometchat-conversations-with-messages>` in a modal
356
+
357
+ The composite renders a 3-panel layout (Conversations + Messages + Details) and needs **≥ 1024px** of horizontal space. Modals are typically 480–960px wide; the Details panel ends up as empty whitespace and the layout looks broken (one column unused, X close button orphaned). Use the **Two-pane** pattern (Pattern A0) for inbox-in-modal, or the **Granular** 1:1 pattern (Pattern A) for "Contact seller"-style direct chat.
358
+
359
+ ### Pattern A0 — Inbox in modal (Two-pane: Conversations + Messages)
360
+
361
+ For "click → open a modal showing the user's inbox + selected thread" (Slack-in-a-popup style).
362
+
363
+ ```typescript
364
+ // inbox-modal.component.ts
365
+ import { Component, OnInit } from "@angular/core";
366
+ import { MatDialogRef } from "@angular/material/dialog";
367
+ import { CometChat } from "@cometchat/chat-sdk-javascript";
368
+ import {
369
+ CometChatConversations,
370
+ CometChatMessages,
371
+ } from "@cometchat/chat-uikit-angular";
372
+ import { CUSTOM_ELEMENTS_SCHEMA } from "@angular/core";
373
+ import { CommonModule } from "@angular/common";
374
+
375
+ @Component({
376
+ selector: "app-inbox-modal",
377
+ standalone: true,
378
+ imports: [CommonModule, CometChatConversations, CometChatMessages],
379
+ schemas: [CUSTOM_ELEMENTS_SCHEMA],
380
+ template: `
381
+ <div style="display: flex; width: 800px; height: 600px;">
382
+ <cometchat-conversations
383
+ style="flex: 0 0 320px; border-right: 1px solid #e5e7eb;"
384
+ [activeConversation]="activeConversation"
385
+ [onItemClick]="onConversationClick"
386
+ ></cometchat-conversations>
387
+ <cometchat-messages
388
+ *ngIf="activeUser || activeGroup; else empty"
389
+ [user]="activeUser"
390
+ [group]="activeGroup"
391
+ style="flex: 1 1 auto;"
392
+ ></cometchat-messages>
393
+ <ng-template #empty>
394
+ <div style="flex: 1; display: flex; align-items: center; justify-content: center; color: #9ca3af;">
395
+ Select a conversation
396
+ </div>
397
+ </ng-template>
398
+ </div>
399
+ `,
400
+ })
401
+ export class InboxModalComponent {
402
+ activeConversation: CometChat.Conversation | null = null;
403
+ activeUser: CometChat.User | null = null;
404
+ activeGroup: CometChat.Group | null = null;
405
+
406
+ constructor(public dialogRef: MatDialogRef<InboxModalComponent>) {}
407
+
408
+ onConversationClick = (conv: CometChat.Conversation): void => {
409
+ this.activeConversation = conv;
410
+ const target = conv.getConversationWith();
411
+ if (target instanceof CometChat.User) {
412
+ this.activeUser = target;
413
+ this.activeGroup = null;
414
+ } else {
415
+ this.activeGroup = target as CometChat.Group;
416
+ this.activeUser = null;
417
+ }
418
+ };
419
+ }
420
+ ```
421
+
422
+ ```typescript
423
+ // Trigger:
424
+ this.dialog.open(InboxModalComponent, { panelClass: "inbox-dialog" });
425
+ ```
426
+
427
+ Why this works in modal sizing where the composite doesn't:
428
+ - **No third panel** — Conversations (left) + Messages (right) consumes the entire dialog width.
429
+ - **Explicit flex sizing** — Conversations is fixed-width (`flex: 0 0 320px`), Messages takes the rest (`flex: 1 1 auto`). No empty whitespace.
430
+ - **Empty state handled** — `*ngIf` shows a "Select a conversation" placeholder until the user clicks one.
431
+
432
+ ### Pattern A — Angular Material MatDialog (recommended)
433
+
434
+ ```typescript
435
+ // chat-dialog.component.ts
436
+ import { Component, Inject } from "@angular/core";
437
+ import { MAT_DIALOG_DATA, MatDialogRef } from "@angular/material/dialog";
438
+ import { CometChat } from "@cometchat/chat-sdk-javascript";
439
+ import {
440
+ CometChatMessageHeader,
441
+ CometChatMessageList,
442
+ CometChatMessageComposer,
443
+ } from "@cometchat/chat-uikit-angular";
444
+ import { CUSTOM_ELEMENTS_SCHEMA } from "@angular/core";
445
+
446
+ @Component({
447
+ selector: "app-chat-dialog",
448
+ standalone: true,
449
+ imports: [CometChatMessageHeader, CometChatMessageList, CometChatMessageComposer],
450
+ schemas: [CUSTOM_ELEMENTS_SCHEMA],
451
+ template: `
452
+ <div style="width: 480px; height: 600px; display: flex; flex-direction: column;">
453
+ <cometchat-message-header
454
+ [user]="data.user"
455
+ [onBack]="close"
456
+ [hideBackButton]="false"
457
+ ></cometchat-message-header>
458
+ <cometchat-message-list
459
+ [user]="data.user"
460
+ style="flex: 1; overflow: hidden;"
461
+ ></cometchat-message-list>
462
+ <cometchat-message-composer [user]="data.user"></cometchat-message-composer>
463
+ </div>
464
+ `,
465
+ })
466
+ export class ChatDialogComponent {
467
+ constructor(
468
+ public dialogRef: MatDialogRef<ChatDialogComponent>,
469
+ @Inject(MAT_DIALOG_DATA) public data: { user: CometChat.User }
470
+ ) {}
471
+
472
+ close = (): void => this.dialogRef.close();
473
+ }
474
+ ```
475
+
476
+ ```typescript
477
+ // Trigger from any component:
478
+ import { MatDialog } from "@angular/material/dialog";
479
+
480
+ @Component({ /* ... */ })
481
+ export class ProductComponent {
482
+ constructor(private dialog: MatDialog) {}
483
+
484
+ openChat(sellerUid: string): void {
485
+ CometChat.getUser(sellerUid).then((user) => {
486
+ this.dialog.open(ChatDialogComponent, {
487
+ data: { user },
488
+ panelClass: "chat-dialog",
489
+ disableClose: false,
490
+ });
491
+ });
492
+ }
493
+ }
494
+ ```
495
+
496
+ ### Pattern B — Angular CDK Overlay (no Material dependency)
497
+
498
+ ```typescript
499
+ import { Overlay, OverlayRef } from "@angular/cdk/overlay";
500
+ import { ComponentPortal } from "@angular/cdk/portal";
501
+
502
+ @Component({ /* ... */ })
503
+ export class TriggerComponent {
504
+ private overlayRef: OverlayRef | null = null;
505
+
506
+ constructor(private overlay: Overlay) {}
507
+
508
+ openChat(): void {
509
+ this.overlayRef = this.overlay.create({
510
+ hasBackdrop: true,
511
+ positionStrategy: this.overlay.position().global().centerHorizontally().centerVertically(),
512
+ });
513
+ const portal = new ComponentPortal(ChatDialogComponent);
514
+ this.overlayRef.attach(portal);
515
+ this.overlayRef.backdropClick().subscribe(() => this.overlayRef?.dispose());
516
+ }
517
+ }
518
+ ```
519
+
520
+ ---
521
+
522
+ ## 4. Tab-based placement
523
+
524
+ For full-featured messengers with distinct entry points per content type. Use Angular Material `MatTabGroup` or a custom tab bar.
525
+
526
+ ```typescript
527
+ // chat-tabs.component.ts
528
+ import { Component } from "@angular/core";
529
+ import { MatTabsModule } from "@angular/material/tabs";
530
+ import {
531
+ CometChatConversations,
532
+ CometChatUsers,
533
+ CometChatGroups,
534
+ CometChatCallLogs,
535
+ } from "@cometchat/chat-uikit-angular";
536
+ import { CUSTOM_ELEMENTS_SCHEMA } from "@angular/core";
537
+
538
+ @Component({
539
+ selector: "app-chat-tabs",
540
+ standalone: true,
541
+ imports: [MatTabsModule, CometChatConversations, CometChatUsers, CometChatGroups, CometChatCallLogs],
542
+ schemas: [CUSTOM_ELEMENTS_SCHEMA],
543
+ template: `
544
+ <mat-tab-group style="height: 100vh;" animationDuration="0ms">
545
+ <mat-tab label="Chats">
546
+ <cometchat-conversations
547
+ [onItemClick]="handleConvClick"
548
+ style="height: calc(100vh - 48px);"
549
+ ></cometchat-conversations>
550
+ </mat-tab>
551
+ <mat-tab label="Users">
552
+ <cometchat-users
553
+ [onItemClick]="handleUserClick"
554
+ style="height: calc(100vh - 48px);"
555
+ ></cometchat-users>
556
+ </mat-tab>
557
+ <mat-tab label="Groups">
558
+ <cometchat-groups
559
+ [onItemClick]="handleGroupClick"
560
+ style="height: calc(100vh - 48px);"
561
+ ></cometchat-groups>
562
+ </mat-tab>
563
+ <mat-tab label="Calls">
564
+ <cometchat-call-logs
565
+ style="height: calc(100vh - 48px);"
566
+ ></cometchat-call-logs>
567
+ </mat-tab>
568
+ </mat-tab-group>
569
+ `,
570
+ })
571
+ export class ChatTabsComponent {
572
+ handleConvClick = (conversation: CometChat.Conversation): void => { /* navigate */ };
573
+ handleUserClick = (user: CometChat.User): void => { /* navigate */ };
574
+ handleGroupClick = (group: CometChat.Group): void => { /* navigate */ };
575
+ }
576
+ ```
577
+
578
+ ### Tab wiring notes
579
+
580
+ - `animationDuration="0ms"` prevents the tab content from fading in/out, which can cause CometChat components to re-initialize.
581
+ - Each tab's content needs an explicit height — `calc(100vh - 48px)` subtracts the tab bar height (48px for Material default).
582
+ - For the **Calls** tab, `<cometchat-call-logs>` only works when `@cometchat/calls-sdk-javascript` is installed. Omit the Calls tab if the project doesn't use calling.
583
+
584
+ ---
585
+
586
+ ## 5. Embedded placement
587
+
588
+ Chat inside an existing page section, not its own route.
589
+
590
+ ```typescript
591
+ // product-detail.component.ts
592
+ @Component({
593
+ selector: "app-product-detail",
594
+ standalone: true,
595
+ imports: [
596
+ CommonModule,
597
+ CometChatMessageHeader,
598
+ CometChatMessageList,
599
+ CometChatMessageComposer,
600
+ ],
601
+ schemas: [CUSTOM_ELEMENTS_SCHEMA],
602
+ template: `
603
+ <div class="product-page">
604
+ <div class="product-info">
605
+ <!-- product details -->
606
+ </div>
607
+
608
+ <div class="chat-section">
609
+ <h3>Chat with seller</h3>
610
+ <div style="height: 480px; display: flex; flex-direction: column; border: 1px solid #e8e8e8; border-radius: 8px; overflow: hidden;">
611
+ <ng-container *ngIf="seller; else loadingChat">
612
+ <cometchat-message-header
613
+ [user]="seller"
614
+ [hideBackButton]="true"
615
+ ></cometchat-message-header>
616
+ <cometchat-message-list
617
+ [user]="seller"
618
+ style="flex: 1; overflow: hidden;"
619
+ ></cometchat-message-list>
620
+ <cometchat-message-composer [user]="seller"></cometchat-message-composer>
621
+ </ng-container>
622
+ <ng-template #loadingChat>
623
+ <div style="flex: 1; display: flex; align-items: center; justify-content: center;">
624
+ Loading chat...
625
+ </div>
626
+ </ng-template>
627
+ </div>
628
+ </div>
629
+ </div>
630
+ `,
631
+ })
632
+ export class ProductDetailComponent implements OnInit {
633
+ seller: CometChat.User | undefined;
634
+
635
+ ngOnInit(): void {
636
+ CometChat.getUser(this.product.sellerUid).then((user) => (this.seller = user));
637
+ }
638
+ }
639
+ ```
640
+
641
+ ### Embedded gotchas
642
+
643
+ - **Fixed height required.** CometChat components fill 100% of their parent. Without a bounded height (`height: 480px` or `flex: 1` inside a flex container), the list collapses to zero height and renders empty.
644
+ - **Overflow hidden on the container.** The inner components have their own scroll — the outer container must not scroll over them.
645
+ - Usually the embedded pattern is the wrong default — prefer a Modal trigger from a button on the page, which gives users a dedicated surface for chatting.
646
+
647
+ ---
648
+
649
+ ## Hard rules
650
+
651
+ These apply to ALL placement patterns.
652
+
653
+ 1. **NEVER modify the project's existing router without reading it first.** Understand what's there before adding routes or outlets. Don't replace a user's navigation structure unless they explicitly chose "demo mode."
654
+
655
+ 2. **ALWAYS give CometChat containers a bounded height.** Components fill 100% of their parent. If the parent has no bounded height, components collapse to zero height and look empty. Use `height: 100vh`, `height: calc(100vh - Npx)`, or `flex: 1` inside a flex column.
656
+
657
+ 3. **Pass either `[user]` or `[group]`, never both.** Passing both causes runtime errors. Branch in the template based on which one is set.
658
+
659
+ 4. **Resolve user / group before rendering.** The `[user]` and `[group]` inputs expect `CometChat.User` and `CometChat.Group` instances — not bare UID strings. Fetch via `CometChat.getUser(uid)` / `CometChat.getGroup(guid)` in `ngOnInit` and gate the render on the resolved object with `*ngIf`.
660
+
661
+ 5. **Wire `[onThreadRepliesClick]` if you want threads**, or leave it unwired to keep the thread option hidden. The `[onThreadRepliesClick]` input is an `@Input()` callback — use `[onThreadRepliesClick]="myFn"` (square brackets). See `cometchat-angular-components` § 11 for the full threading pattern.
662
+
663
+ 6. **For modal placements, set an explicit width and height on the dialog container.** Angular Material dialogs don't constrain their content by default — without explicit dimensions, CometChat components may render at 0px.
664
+
665
+ 6a. **Never use `<cometchat-conversations-with-messages>` (or `<cometchat-users-with-messages>` / `<cometchat-groups-with-messages>`) inside a modal, dialog, drawer, or sidebar.** These composites render a 3-panel layout (List + Messages + Details) and need ≥ 1024px of horizontal space. In a 480–960px modal, the Details panel ends up as empty whitespace and the layout looks broken. Use the Two-pane pattern (`<cometchat-conversations>` + `<cometchat-messages>`, see § 3 Pattern A0) for inbox-in-modal, or the Granular pattern (`<cometchat-message-header>` + `-message-list>` + `-message-composer>`, see § 3 Pattern A) for 1:1 chat.
666
+
667
+ 7. **For sidebar placements, use `overflow: hidden` on both the sidebar and message area containers.** CometChat components have internal scroll; the outer containers must not add a second scroll layer.
668
+
669
+ 8. **Never animate a CometChat-containing container with CSS `transform`.** `transform` creates a new stacking context, which reparents `position: fixed` overlays (emoji picker, action sheet, reactions popover) and makes them misalign. Animate `left` / `right` / `top` / `bottom` offsets instead.
670
+
671
+ ---
672
+
673
+ ## Skill routing reference
674
+
675
+ | Skill | When to route |
676
+ |---|---|
677
+ | `cometchat-angular-core` | Always first — init, login, module setup |
678
+ | `cometchat-angular-components` | For component prop details — always |
679
+ | `cometchat-angular-placement` | This skill — picking + wiring a placement |
680
+ | `cometchat-angular-patterns` | Angular-specific routing, lazy loading, guards |
681
+ | `cometchat-angular-theming` | Customize colors / typography / dark mode |
682
+ | `cometchat-angular-features` | Calls, extensions, AI — the "add a feature" flow |
683
+ | `cometchat-angular-customization` | Custom slot views, text formatters, events |
684
+ | `cometchat-angular-production` | Server-side auth tokens |
685
+ | `cometchat-angular-troubleshooting` | Blank chat / height issues / dialog sizing |