Documentation Index Fetch the complete documentation index at: https://cometchat-22654f5b-docs-android-v6-beta2.mintlify.app/llms.txt
Use this file to discover all available pages before exploring further.
Overview
The CometChatMessageComposer is a feature-rich Angular component for composing and sending messages in chat applications. It provides a comprehensive set of features including text input, file attachments, emoji picker, voice recording, @mentions, and optional rich text editing capabilities similar to Slack.
The component follows a Service-Based Architecture where:
MessageComposerService handles all SDK interactions for sending messages, typing indicators, and file uploads
RichTextEditorService manages rich text editing functionality when enabled (custom implementation using native browser APIs)
Component @Input properties provide extensive customization options
Angular Signals power reactive state management for optimal performance
Key Features
Auto-Expanding Text Input : Textarea that grows with content up to a configurable maximum height
Multiple Attachments : Support for images, videos, audio, and files with drag-and-drop
Rich Text Editing : Optional rich text formatting using custom RichTextEditorService (bold, italic, lists, code blocks, etc.)
Emoji Picker : Built-in emoji keyboard with category navigation
Voice Recording : Record and send audio messages with waveform visualization
@Mentions : Tag users in messages with autocomplete suggestions
Reply & Edit Modes : Reply to specific messages or edit existing ones
Full Accessibility : WCAG 2.1 Level AA compliant with keyboard navigation and screen reader support
Extensive Customization : Template inputs for all UI sections
Lightweight : No external rich text editor dependencies (100KB+ smaller bundle)
Basic Usage
Simple Implementation with User
import { Component } from '@angular/core' ;
import { CometChat } from '@cometchat/chat-sdk-javascript' ;
import { CometChatMessageComposerComponent } from '@cometchat/chat-uikit-angular' ;
@ Component ({
selector: 'app-chat' ,
standalone: true ,
imports: [ CometChatMessageComposerComponent ],
template: `
<cometchat-message-composer
[user]="selectedUser"
(sendButtonClick)="onMessageSent($event)"
(error)="onError($event)"
></cometchat-message-composer>
`
})
export class ChatComponent {
selectedUser !: CometChat . User ;
onMessageSent ( message : CometChat . BaseMessage ) : void {
console . log ( 'Message sent:' , message );
}
onError ( error : CometChat . CometChatException ) : void {
console . error ( 'Error:' , error );
}
}
See all 27 lines
Simple Implementation with Group
import { Component } from '@angular/core' ;
import { CometChat } from '@cometchat/chat-sdk-javascript' ;
import { CometChatMessageComposerComponent } from '@cometchat/chat-uikit-angular' ;
@ Component ({
selector: 'app-group-chat' ,
standalone: true ,
imports: [ CometChatMessageComposerComponent ],
template: `
<cometchat-message-composer
[group]="selectedGroup"
[placeholderText]="'Type a message to the group...'"
(sendButtonClick)="onMessageSent($event)"
></cometchat-message-composer>
`
})
export class GroupChatComponent {
selectedGroup !: CometChat . Group ;
onMessageSent ( message : CometChat . BaseMessage ) : void {
console . log ( 'Group message sent:' , message );
}
}
See all 23 lines
With Rich Text Editing
< cometchat - message - composer
[ user ] = "selectedUser"
[ enableRichText ] = "true"
( sendButtonClick ) = "onMessageSent($event)"
( textChange ) = "onTextChange($event)"
> </ cometchat - message - composer >
With Attachments and Drag-Drop
< cometchat - message - composer
[ user ] = "selectedUser"
[ enableDragDrop ] = "true"
[ maxAttachments ] = "5"
[ maxFileSize ] = "10485760"
[ showAttachmentPreview ] = "true"
( attachmentAdded ) = "onAttachmentAdded($event)"
( attachmentRemoved ) = "onAttachmentRemoved($event)"
> </ cometchat - message - composer >
Layout Modes
The CometChatMessageComposer supports two layout modes to accommodate different UI requirements and screen sizes.
Single-Line Layout (Default)
The single-line layout arranges elements horizontally in a row:
Attachment button on the left
Input area in the center (grows to fill available space)
Auxiliary buttons (emoji, stickers, voice) on the right
Send button on the far right
This layout is ideal for:
Desktop applications with ample horizontal space
Chat interfaces where vertical space is limited
Traditional messaging UIs similar to Slack or Teams
import { Component } from '@angular/core' ;
import { CometChat } from '@cometchat/chat-sdk-javascript' ;
import { CometChatMessageComposerComponent } from '@cometchat/chat-uikit-angular' ;
@ Component ({
selector: 'app-single-line-composer' ,
standalone: true ,
imports: [ CometChatMessageComposerComponent ],
template: `
<cometchat-message-composer
[user]="selectedUser"
[layout]="'single-line'"
(sendButtonClick)="onMessageSent($event)"
></cometchat-message-composer>
`
})
export class SingleLineComposerComponent {
selectedUser !: CometChat . User ;
onMessageSent ( message : CometChat . BaseMessage ) : void {
console . log ( 'Message sent:' , message );
}
}
See all 23 lines
Multiline Layout
The multiline layout arranges elements vertically:
Input area at the top spanning full width
All action buttons in a horizontal row below (attachment, emoji, stickers, voice, send)
This layout is ideal for:
Mobile applications where horizontal space is limited
Interfaces where you want to maximize input area width
Chat UIs that prioritize typing space over button visibility
import { Component } from '@angular/core' ;
import { CometChat } from '@cometchat/chat-sdk-javascript' ;
import { CometChatMessageComposerComponent } from '@cometchat/chat-uikit-angular' ;
@ Component ({
selector: 'app-multiline-composer' ,
standalone: true ,
imports: [ CometChatMessageComposerComponent ],
template: `
<cometchat-message-composer
[user]="selectedUser"
[layout]="'multiline'"
(sendButtonClick)="onMessageSent($event)"
></cometchat-message-composer>
`
})
export class MultilineComposerComponent {
selectedUser !: CometChat . User ;
onMessageSent ( message : CometChat . BaseMessage ) : void {
console . log ( 'Message sent:' , message );
}
}
See all 23 lines
Dynamic Layout Switching
You can dynamically switch between layouts based on screen size or user preferences:
import { Component , HostListener } from '@angular/core' ;
import { CometChat } from '@cometchat/chat-sdk-javascript' ;
import { CometChatMessageComposerComponent } from '@cometchat/chat-uikit-angular' ;
@ Component ({
selector: 'app-responsive-composer' ,
standalone: true ,
imports: [ CometChatMessageComposerComponent ],
template: `
<cometchat-message-composer
[user]="selectedUser"
[layout]="composerLayout"
(sendButtonClick)="onMessageSent($event)"
></cometchat-message-composer>
`
})
export class ResponsiveComposerComponent {
selectedUser !: CometChat . User ;
composerLayout : 'single-line' | 'multiline' = 'single-line' ;
@ HostListener ( 'window:resize' , [ '$event' ])
onResize () : void {
// Switch to multiline layout on mobile devices
this . composerLayout = window . innerWidth < 768 ? 'multiline' : 'single-line' ;
}
ngOnInit () : void {
this . onResize (); // Set initial layout
}
onMessageSent ( message : CometChat . BaseMessage ) : void {
console . log ( 'Message sent:' , message );
}
}
See all 34 lines
Layout with Rich Text Editing
Both layouts work seamlessly with rich text editing:
<!-- Single - line layout with rich text -->
< cometchat - message - composer
[ user ] = "selectedUser"
[ layout ] = "'single-line'"
[ enableRichText ] = "true"
> </ cometchat - message - composer >
<!-- Multiline layout with rich text -->
< cometchat - message - composer
[ user ] = "selectedUser"
[ layout ] = "'multiline'"
[ enableRichText ] = "true"
> </ cometchat - message - composer >
See all 13 lines
Note: All composer features (attachments, emoji picker, voice recording, mentions, etc.) work identically in both layouts. The only difference is the visual arrangement of elements.
Properties
Entity Configuration Properties
Property Type Default Description userCometChat.UserundefinedThe user to send messages to (for 1-on-1 conversations). Mutually exclusive with group. groupCometChat.GroupundefinedThe group to send messages to (for group conversations). Mutually exclusive with user. parentMessageIdnumberundefinedParent message ID for threaded replies. When set, messages are sent as replies.
Layout Configuration Properties
Property Type Default Description layout'single-line' | 'multiline''single-line'Layout mode for the composer. 'single-line' arranges elements horizontally (attachment button on left, input in center, auxiliary buttons on right). 'multiline' arranges elements vertically (input area on top spanning full width, all buttons in a row below).
Text Input Configuration Properties
Property Type Default Description placeholderTextstring'message_composer_placeholder'Placeholder text for the input area (localization key) initialComposerTextstring''Initial text to pre-fill in the composer textstring''Controlled text value for the composer maxHeightnumber200Maximum height for the text input area in pixels enterKeyBehaviorEnterKeyBehaviorSendMessageBehavior when Enter is pressed: SendMessage, NewLine, or None
Attachment Configuration Properties
Property Type Default Description attachmentOptionsCometChatMessageComposerAction[]undefinedCustom attachment options for the attachment menu maxAttachmentsnumber10Maximum number of attachments allowed allowedFileTypesstring[]undefinedAllowed MIME types for attachments (e.g., ['image/*', 'application/pdf']) maxFileSizenumberundefinedMaximum file size in bytes showAttachmentPreviewbooleantrueShow attachment preview thumbnails before sending enableDragDropbooleantrueEnable drag-and-drop file uploads
Hide Option Properties
Property Type Default Description hideAttachmentButtonbooleanfalseHide the attachment button hideImageAttachmentOptionbooleanfalseHide image option in attachment menu hideVideoAttachmentOptionbooleanfalseHide video option in attachment menu hideAudioAttachmentOptionbooleanfalseHide audio option in attachment menu hideFileAttachmentOptionbooleanfalseHide file option in attachment menu hidePollsOptionbooleanfalseHide polls option in attachment menu hideCollaborativeDocumentOptionbooleanfalseHide collaborative document option hideCollaborativeWhiteboardOptionbooleanfalseHide collaborative whiteboard option hideEmojiKeyboardButtonbooleanfalseHide the emoji picker button hideVoiceRecordingButtonbooleanfalseHide the voice recording button hideStickersButtonbooleanfalseHide the stickers button hideLiveReactionbooleanfalseHide the live reaction button hideSendButtonbooleanfalseHide the send button
Mentions Configuration Properties
Property Type Default Description disableMentionsbooleanfalseDisable @mentions functionality disableMentionAllbooleanfalseDisable @all mention option in groups mentionAllLabelstring'all'Label for the @all mention option mentionsUsersRequestBuilderCometChat.UsersRequestBuilderundefinedCustom request builder for fetching users for mentions mentionsGroupMembersRequestBuilderCometChat.GroupMembersRequestBuilderundefinedCustom request builder for fetching group members for mentions
Rich Text Configuration Properties
Property Type Default Description enableRichTextbooleantrueEnable rich text editing. When disabled, toolbar toggle button is hidden and pasting/adding content won’t apply rich text formatting. Mentions and other formatters still work independently. hideRichTextToolbarbooleanfalseHide the rich text formatting toolbar. When showToolbarToggle is enabled, the toggle overrides this setting. showBubbleMenuOnSelectionbooleantrueShow floating bubble menu when text is selected (Web/Desktop only) showToolbarTogglebooleantrueShow a toggle button to show/hide the fixed toolbar. Emits toolbarToggleClick with ‘active’ or ‘inactive’ state.
Other Configuration Properties
Property Type Default Description disableTypingEventsbooleanfalseDisable sending typing indicator events disableSoundForMessagebooleanfalseDisable sound when sending messages customSoundForMessagestringundefinedCustom sound URL for message sent notification liveReactionIconstringundefinedCustom icon for live reaction button messageToEditCometChat.BaseMessageundefinedMessage to edit (enables edit mode) messageToReplyCometChat.BaseMessageundefinedMessage to reply to (enables reply preview) textFormattersCometChatTextFormatter[]undefinedArray of text formatters to apply showToolbarTogglebooleantrueWhether to show the toolbar toggle button for expanding/collapsing the action toolbar
Template Properties
Property Type Default Description headerViewTemplateRef<any>undefinedCustom template for the header section above the input footerViewTemplateRef<any>undefinedCustom template for the footer section below the input sendButtonViewTemplateRef<any>undefinedCustom template for the send button auxiliaryButtonViewTemplateRef<any>undefinedCustom template for auxiliary action buttons secondaryButtonViewTemplateRef<any>undefinedCustom template for secondary action buttons attachmentIconViewTemplateRef<any>undefinedCustom template for the attachment icon voiceRecordingIconViewTemplateRef<any>undefinedCustom template for the voice recording icon emojiIconViewTemplateRef<any>undefinedCustom template for the emoji icon
Events
Event Payload Type Description textChangestringEmitted when the text content changes sendButtonClickCometChat.BaseMessageEmitted when a message is sent successfully errorCometChat.CometChatExceptionEmitted when an error occurs closePreviewvoidEmitted when the reply/edit preview is closed attachmentAddedFileEmitted when an attachment is added attachmentRemovedFileEmitted when an attachment is removed mentionSelectedCometChat.User | CometChat.GroupMemberEmitted when a mention is selected
Usage Patterns
CometChatMessageComposer supports two usage patterns for receiving the active user or group context.
Using Service
Using Props
When used alongside cometchat-conversations, the composer automatically subscribes to ChatStateService. No explicit [user] or [group] input is needed — the component sends messages to the active conversation. import { Component } from '@angular/core' ;
import {
CometChatConversationsComponent ,
CometChatMessageHeaderComponent ,
CometChatMessageListComponent ,
CometChatMessageComposerComponent ,
} from '@cometchat/chat-uikit-angular' ;
@ Component ({
selector: 'app-chat' ,
standalone: true ,
imports: [
CometChatConversationsComponent ,
CometChatMessageHeaderComponent ,
CometChatMessageListComponent ,
CometChatMessageComposerComponent ,
],
template: `
<div class="chat-layout">
<cometchat-conversations
(itemClick)="onConversationClick($event)"
></cometchat-conversations>
<div class="chat-panel">
<cometchat-message-header></cometchat-message-header>
<cometchat-message-list></cometchat-message-list>
<!-- Automatically targets the active conversation -->
<cometchat-message-composer></cometchat-message-composer>
</div>
</div>
` ,
})
export class ChatComponent {
onConversationClick ( conversation : any ) : void {}
}
See all 35 lines
This is the recommended approach. The composer stays in sync with the conversation list without manual wiring.
Pass [user] or [group] directly to control which conversation the composer targets. This overrides ChatStateService state. import { Component } from '@angular/core' ;
import { CometChat } from '@cometchat/chat-sdk-javascript' ;
import { CometChatMessageComposerComponent } from '@cometchat/chat-uikit-angular' ;
@ Component ({
selector: 'app-chat' ,
standalone: true ,
imports: [ CometChatMessageComposerComponent ],
template: `
<cometchat-message-composer
[user]="selectedUser"
(sendButtonClick)="onMessageSent($event)"
></cometchat-message-composer>
` ,
})
export class ChatComponent {
selectedUser !: CometChat . User ;
onMessageSent ( message : CometChat . BaseMessage ) : void {}
}
See all 19 lines
For group conversations: < cometchat - message - composer
[ group ] = "selectedGroup"
( sendButtonClick ) = "onMessageSent($event)"
> </ cometchat - message - composer >
When [user] or [group] inputs are provided, they take priority over ChatStateService state for that component instance.
Advanced Usage
Reply Mode (Threaded Messages)
Enable reply mode by setting the parentMessageId to reply to a specific message:
import { Component } from '@angular/core' ;
import { CometChat } from '@cometchat/chat-sdk-javascript' ;
import { CometChatMessageComposerComponent } from '@cometchat/chat-uikit-angular' ;
@ Component ({
selector: 'app-reply-composer' ,
standalone: true ,
imports: [ CometChatMessageComposerComponent ],
template: `
<cometchat-message-composer
[user]="selectedUser"
[parentMessageId]="replyToMessageId"
(sendButtonClick)="onReplySent($event)"
(closePreview)="cancelReply()"
></cometchat-message-composer>
`
})
export class ReplyComposerComponent {
selectedUser !: CometChat . User ;
replyToMessageId ?: number ;
replyToMessage ( message : CometChat . BaseMessage ) : void {
this . replyToMessageId = message . getId ();
}
onReplySent ( message : CometChat . BaseMessage ) : void {
console . log ( 'Reply sent:' , message );
this . replyToMessageId = undefined ;
}
cancelReply () : void {
this . replyToMessageId = undefined ;
}
}
See all 34 lines
Edit Mode
Enable edit mode by setting the messageToEdit property:
import { Component } from '@angular/core' ;
import { CometChat } from '@cometchat/chat-sdk-javascript' ;
import { CometChatMessageComposerComponent } from '@cometchat/chat-uikit-angular' ;
@ Component ({
selector: 'app-edit-composer' ,
standalone: true ,
imports: [ CometChatMessageComposerComponent ],
template: `
<cometchat-message-composer
[user]="selectedUser"
[messageToEdit]="editingMessage"
(sendButtonClick)="onMessageEdited($event)"
(closePreview)="cancelEdit()"
></cometchat-message-composer>
`
})
export class EditComposerComponent {
selectedUser !: CometChat . User ;
editingMessage ?: CometChat . BaseMessage ;
editMessage ( message : CometChat . BaseMessage ) : void {
this . editingMessage = message ;
}
onMessageEdited ( message : CometChat . BaseMessage ) : void {
console . log ( 'Message edited:' , message );
this . editingMessage = undefined ;
}
cancelEdit () : void {
this . editingMessage = undefined ;
}
}
See all 34 lines
Rich Text Editing
Enable Slack-like rich text editing with formatting toolbar using the custom RichTextEditorService:
import { Component } from '@angular/core' ;
import { CometChat } from '@cometchat/chat-sdk-javascript' ;
import { CometChatMessageComposerComponent } from '@cometchat/chat-uikit-angular' ;
@ Component ({
selector: 'app-rich-text-composer' ,
standalone: true ,
imports: [ CometChatMessageComposerComponent ],
template: `
<cometchat-message-composer
[user]="selectedUser"
[enableRichText]="true"
[hideRichTextToolbar]="false"
(sendButtonClick)="onMessageSent($event)"
></cometchat-message-composer>
`
})
export class RichTextComposerComponent {
selectedUser !: CometChat . User ;
onMessageSent ( message : CometChat . BaseMessage ) : void {
console . log ( 'Rich text message sent:' , message );
// Message metadata will contain rich text formatting info
}
}
See all 25 lines
Rich Text Toolbar Features:
Bold (Ctrl+B / Cmd+B): Make text bold
Italic (Ctrl+I / Cmd+I): Make text italic
Underline (Ctrl+U / Cmd+U): Underline text
Strikethrough : Strike through text
Inline Code : Format as inline code
Link : Insert hyperlinks with validation
Ordered List : Create numbered lists
Bullet List : Create bulleted lists
Code Block : Insert code blocks
Blockquote : Add quoted text
Implementation Details:
Uses custom RichTextEditorService built on native browser APIs
No external dependencies
Smaller bundle size (100KB+ reduction)
Full keyboard shortcut support
XSS protection with HTML sanitization
Unicode and emoji support
Undo/redo with history grouping (500ms delay)
Rich Text Enhancements
The message composer includes advanced rich text features for improved user experience:
Enable a Slack-like floating bubble menu that appears when text is selected (Web/Desktop only):
import { Component } from '@angular/core' ;
import { CometChat } from '@cometchat/chat-sdk-javascript' ;
import { CometChatMessageComposerComponent } from '@cometchat/chat-uikit-angular' ;
@ Component ({
selector: 'app-bubble-menu-composer' ,
standalone: true ,
imports: [ CometChatMessageComposerComponent ],
template: `
<cometchat-message-composer
[user]="selectedUser"
[enableRichText]="true"
[showBubbleMenuOnSelection]="true"
[hideRichTextToolbar]="true"
(sendButtonClick)="onMessageSent($event)"
></cometchat-message-composer>
`
})
export class BubbleMenuComposerComponent {
selectedUser !: CometChat . User ;
onMessageSent ( message : CometChat . BaseMessage ) : void {
console . log ( 'Message sent:' , message );
}
}
See all 25 lines
Bubble Menu Features:
Appears only when text is selected
Automatically disabled on mobile/touch devices
Quick access to formatting: bold, italic, underline, strikethrough, link
Smart positioning above selected text
Keyboard support (Escape to close)
Smooth fade in/out animations
Keep the formatting toolbar visible at all times for improved discoverability:
< cometchat - message - composer
[ user ] = "selectedUser"
[ enableRichText ] = "true"
( sendButtonClick ) = "onMessageSent($event)"
> </ cometchat - message - composer >
Benefits:
Toolbar remains visible even when editor is empty
Improved discoverability of formatting options
Consistent UI with no layout shifts
Ideal for professional/business contexts
Combining All Features
Use all rich text enhancements together:
< cometchat - message - composer
[ user ] = "selectedUser"
[ enableRichText ] = "true"
[ showBubbleMenuOnSelection ] = "true"
( sendButtonClick ) = "onMessageSent($event)"
> </ cometchat - message - composer >
This configuration provides:
Floating bubble menu for quick text selection formatting
Toolbar toggle button for showing/hiding the fixed toolbar
Full keyboard shortcut support
@Mentions with Custom Request Builder
Configure mentions with custom user/member fetching:
import { Component , OnInit } from '@angular/core' ;
import { CometChat } from '@cometchat/chat-sdk-javascript' ;
import { CometChatMessageComposerComponent } from '@cometchat/chat-uikit-angular' ;
@ Component ({
selector: 'app-mentions-composer' ,
standalone: true ,
imports: [ CometChatMessageComposerComponent ],
template: `
<cometchat-message-composer
[group]="selectedGroup"
[disableMentions]="false"
[disableMentionAll]="false"
[mentionAllLabel]="'everyone'"
[mentionsGroupMembersRequestBuilder]="membersBuilder"
(mentionSelected)="onMentionSelected($event)"
(sendButtonClick)="onMessageSent($event)"
></cometchat-message-composer>
`
})
export class MentionsComposerComponent implements OnInit {
selectedGroup !: CometChat . Group ;
membersBuilder !: CometChat . GroupMembersRequestBuilder ;
ngOnInit () : void {
// Custom builder to fetch only active members
this . membersBuilder = new CometChat . GroupMembersRequestBuilder ( this . selectedGroup . getGuid ())
. setLimit ( 20 )
. setScopes ([ 'admin' , 'moderator' , 'participant' ]);
}
onMentionSelected ( user : CometChat . User | CometChat . GroupMember ) : void {
console . log ( 'Mentioned:' , user . getName ());
}
onMessageSent ( message : CometChat . BaseMessage ) : void {
console . log ( 'Message with mentions sent:' , message );
// Message metadata will contain mention information
}
}
See all 40 lines
File Attachments with Validation
Configure attachment handling with file type and size validation:
import { Component } from '@angular/core' ;
import { CometChat } from '@cometchat/chat-sdk-javascript' ;
import { CometChatMessageComposerComponent } from '@cometchat/chat-uikit-angular' ;
@ Component ({
selector: 'app-attachments-composer' ,
standalone: true ,
imports: [ CometChatMessageComposerComponent ],
template: `
<cometchat-message-composer
[user]="selectedUser"
[enableDragDrop]="true"
[maxAttachments]="5"
[maxFileSize]="10485760"
[allowedFileTypes]="allowedTypes"
[showAttachmentPreview]="true"
(attachmentAdded)="onAttachmentAdded($event)"
(attachmentRemoved)="onAttachmentRemoved($event)"
(error)="onError($event)"
></cometchat-message-composer>
`
})
export class AttachmentsComposerComponent {
selectedUser !: CometChat . User ;
// Allow images, PDFs, and common document types
allowedTypes = [
'image/jpeg' ,
'image/png' ,
'image/gif' ,
'application/pdf' ,
'application/msword' ,
'application/vnd.openxmlformats-officedocument.wordprocessingml.document'
];
onAttachmentAdded ( file : File ) : void {
console . log ( 'Attachment added:' , file . name , file . size );
}
onAttachmentRemoved ( file : File ) : void {
console . log ( 'Attachment removed:' , file . name );
}
onError ( error : CometChat . CometChatException ) : void {
// Handle file validation errors
console . error ( 'Error:' , error . message );
}
}
See all 48 lines
Voice Recording
The composer includes built-in voice recording functionality:
< cometchat - message - composer
[ user ] = "selectedUser"
[ hideVoiceRecordingButton ] = "false"
( sendButtonClick ) = "onMessageSent($event)"
> </ cometchat - message - composer >
When the microphone button is clicked:
The CometChatMediaRecorder component appears
User can record audio with waveform visualization
Recording duration is displayed
User can cancel or complete the recording
Completed recordings are sent as audio messages
Customization with Templates
import { Component } from '@angular/core' ;
import { CommonModule } from '@angular/common' ;
import { CometChat } from '@cometchat/chat-sdk-javascript' ;
import { CometChatMessageComposerComponent } from '@cometchat/chat-uikit-angular' ;
@ Component ({
selector: 'app-custom-send' ,
standalone: true ,
imports: [ CommonModule , CometChatMessageComposerComponent ],
template: `
<cometchat-message-composer
[user]="selectedUser"
[sendButtonView]="customSendButton"
>
<ng-template #customSendButton>
<button
class="custom-send-btn"
aria-label="Send message">
<span class="send-icon">➤</span>
<span class="send-text">Send</span>
</button>
</ng-template>
</cometchat-message-composer>
` ,
styles: [ `
.custom-send-btn {
display: flex;
align-items: center;
gap: 6px;
padding: 8px 16px;
background: linear-gradient(135deg, #6852D6, #8B7AFF);
color: white;
border: none;
border-radius: 20px;
cursor: pointer;
font-weight: 500;
transition: transform 0.2s, box-shadow 0.2s;
}
.custom-send-btn:hover {
transform: scale(1.05);
box-shadow: 0 4px 12px rgba(104, 82, 214, 0.4);
}
.custom-send-btn:focus {
outline: 2px solid #6852D6;
outline-offset: 2px;
}
.send-icon {
font-size: 14px;
}
` ]
})
export class CustomSendComponent {
selectedUser !: CometChat . User ;
}
See all 54 lines
import { Component } from '@angular/core' ;
import { CommonModule } from '@angular/common' ;
import { CometChat } from '@cometchat/chat-sdk-javascript' ;
import { CometChatMessageComposerComponent } from '@cometchat/chat-uikit-angular' ;
@ Component ({
selector: 'app-custom-header' ,
standalone: true ,
imports: [ CommonModule , CometChatMessageComposerComponent ],
template: `
<cometchat-message-composer
[user]="selectedUser"
[parentMessageId]="replyToMessageId"
[headerView]="customHeader"
(closePreview)="cancelReply()"
>
<ng-template #customHeader>
@if (replyToMessage) {
<div class="custom-reply-preview">
<div class="reply-indicator">
<span class="reply-icon">↩</span>
<span class="reply-label">Replying to {{ replyToMessage.getSender().getName() }}</span>
</div>
<div class="reply-content">
{{ getMessagePreview(replyToMessage) }}
</div>
<button
class="close-btn"
(click)="cancelReply()"
aria-label="Cancel reply">
✕
</button>
</div>
}
</ng-template>
</cometchat-message-composer>
` ,
styles: [ `
.custom-reply-preview {
display: flex;
align-items: center;
padding: 8px 12px;
background: #f5f5f5;
border-left: 3px solid #6852D6;
border-radius: 4px;
margin-bottom: 8px;
}
.reply-indicator {
display: flex;
align-items: center;
gap: 6px;
color: #6852D6;
font-weight: 500;
font-size: 12px;
}
.reply-content {
flex: 1;
margin-left: 12px;
color: #666;
font-size: 13px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.close-btn {
background: none;
border: none;
color: #999;
cursor: pointer;
padding: 4px;
font-size: 14px;
}
.close-btn:hover {
color: #333;
}
` ]
})
export class CustomHeaderComponent {
selectedUser !: CometChat . User ;
replyToMessageId ?: number ;
replyToMessage ?: CometChat . BaseMessage ;
getMessagePreview ( message : CometChat . BaseMessage ) : string {
if ( message . getType () === 'text' ) {
return ( message as CometChat . TextMessage ). getText ();
}
return `[ ${ message . getType () } ]` ;
}
cancelReply () : void {
this . replyToMessageId = undefined ;
this . replyToMessage = undefined ;
}
}
See all 94 lines
Add custom action buttons alongside the default emoji and voice buttons:
import { Component } from '@angular/core' ;
import { CommonModule } from '@angular/common' ;
import { CometChat } from '@cometchat/chat-sdk-javascript' ;
import { CometChatMessageComposerComponent } from '@cometchat/chat-uikit-angular' ;
@ Component ({
selector: 'app-custom-auxiliary' ,
standalone: true ,
imports: [ CommonModule , CometChatMessageComposerComponent ],
template: `
<cometchat-message-composer
[user]="selectedUser"
[auxiliaryButtonView]="customAuxiliary"
>
<ng-template #customAuxiliary>
<div class="custom-auxiliary-buttons">
<button
class="aux-btn"
(click)="openGifPicker()"
aria-label="Send GIF">
🎬
</button>
<button
class="aux-btn"
(click)="openLocationPicker()"
aria-label="Share location">
📍
</button>
<button
class="aux-btn"
(click)="openScheduler()"
aria-label="Schedule message">
⏰
</button>
</div>
</ng-template>
</cometchat-message-composer>
` ,
styles: [ `
.custom-auxiliary-buttons {
display: flex;
gap: 4px;
}
.aux-btn {
background: none;
border: none;
font-size: 20px;
cursor: pointer;
padding: 6px;
border-radius: 4px;
transition: background-color 0.2s;
}
.aux-btn:hover {
background-color: rgba(0, 0, 0, 0.05);
}
.aux-btn:focus {
outline: 2px solid #6852D6;
outline-offset: 2px;
}
` ]
})
export class CustomAuxiliaryComponent {
selectedUser !: CometChat . User ;
openGifPicker () : void {
console . log ( 'Opening GIF picker' );
}
openLocationPicker () : void {
console . log ( 'Opening location picker' );
}
openScheduler () : void {
console . log ( 'Opening message scheduler' );
}
}
See all 76 lines
Keyboard Accessibility
CometChatMessageComposer is fully keyboard accessible and meets WCAG 2.1 Level AA standards.
Keyboard Shortcuts
Key Action Context TabNavigate between interactive elements Global Shift + TabNavigate backwards Global EnterSend message (when enterKeyBehavior is SendMessage) Text input focused Shift + EnterInsert new line Text input focused Enter / SpaceActivate focused button When button is focused EscapeClose open popups (emoji, attachments, mentions) When popup is open ↓ (Down Arrow)Navigate to next mention suggestion When mentions panel is open ↑ (Up Arrow)Navigate to previous mention suggestion When mentions panel is open Enter / TabSelect focused mention When mention is focused Ctrl + BToggle bold (rich text mode) When rich text is enabled Ctrl + IToggle italic (rich text mode) When rich text is enabled Ctrl + UToggle underline (rich text mode) When rich text is enabled
Accessibility Features
ARIA Attributes:
role="textbox" with aria-multiline="true" on the text input
aria-label describing the input purpose
aria-haspopup="menu" and aria-expanded on attachment button
aria-haspopup="dialog" and aria-expanded on emoji button
aria-label="Send message" on send button
aria-label and aria-pressed on voice recording button
role="menu" with role="menuitem" for attachment options
role="listbox" with role="option" for mention suggestions
role="toolbar" on rich text toolbar with proper button labels
Screen Reader Support:
Announces reply/edit preview when shown via aria-live="polite"
Announces recording state changes via aria-live="assertive"
Announces message sent confirmation via aria-live="polite"
Announces attachment added/removed via aria-live="polite"
Announces errors via aria-live="assertive"
Focus Management:
Visible focus indicators (2px border) meeting WCAG contrast requirements
Logical tab order through interactive elements
Focus returns to input after closing popups
Focus trap within menus when open
WCAG 2.1 Compliance:
✅ 2.1.1 Keyboard (Level A) - All functionality available via keyboard
✅ 2.1.2 No Keyboard Trap (Level A) - Users can navigate away using keyboard
✅ 2.4.3 Focus Order (Level A) - Logical focus order
✅ 2.4.7 Focus Visible (Level AA) - Visible focus indicators
✅ 4.1.2 Name, Role, Value (Level A) - Proper ARIA attributes
✅ 4.1.3 Status Messages (Level AA) - Screen reader announcements
Styling with CSS Variables
The CometChatMessageComposer component uses CSS variables for comprehensive theming:
cometchat-message-composer {
/* Background colors */
--cometchat-background-color-01 : #ffffff ;
--cometchat-background-color-02 : #f5f5f5 ;
--cometchat-background-color-03 : #e8e8e8 ;
/* Text colors */
--cometchat-text-color-primary : #141414 ;
--cometchat-text-color-secondary : #727272 ;
--cometchat-text-color-tertiary : #999999 ;
/* Border colors */
--cometchat-border-color-light : #e8e8e8 ;
--cometchat-border-color-default : #dcdcdc ;
/* Primary color */
--cometchat-primary-color : #6852D6 ;
/* Status colors */
--cometchat-success-color : #09C26F ;
--cometchat-error-color : #FF3B30 ;
/* Typography */
--cometchat-font-body-regular : 400 14 px / 20 px Inter, sans-serif ;
--cometchat-font-caption1-regular : 400 12 px / 16 px Inter, sans-serif ;
/* Spacing */
--cometchat-spacing-1 : 4 px ;
--cometchat-spacing-2 : 8 px ;
--cometchat-spacing-3 : 12 px ;
--cometchat-spacing-4 : 16 px ;
/* Border radius */
--cometchat-radius-2 : 8 px ;
--cometchat-radius-3 : 12 px ;
--cometchat-radius-max : 9999 px ;
}
See all 37 lines
Dark Theme Example
.dark-theme cometchat-message-composer {
--cometchat-background-color-01 : #1a1a1a ;
--cometchat-background-color-02 : #2a2a2a ;
--cometchat-background-color-03 : #3a3a3a ;
--cometchat-text-color-primary : #ffffff ;
--cometchat-text-color-secondary : #cccccc ;
--cometchat-text-color-tertiary : #999999 ;
--cometchat-border-color-light : #333333 ;
--cometchat-border-color-default : #444444 ;
}
See all 10 lines
Custom Brand Colors
.branded-composer cometchat-message-composer {
--cometchat-primary-color : #FF6B35 ;
--cometchat-success-color : #00C853 ;
}
Text Formatters
The component supports custom text formatters for automatic text transformation and metadata extraction.
CometChatMentionsFormatter:
Detects @mention patterns in text
Highlights mentions with distinct styling
Extracts mention metadata (user ID, name, position)
Supports @all mentions for groups
CometChatUrlFormatter:
Detects URL patterns (http://, https://, www .)
Converts URLs to clickable links
Opens links in new tabs
Extracts URL metadata
import { Component } from '@angular/core' ;
import { CometChat } from '@cometchat/chat-sdk-javascript' ;
import {
CometChatMessageComposerComponent ,
CometChatMentionsFormatter ,
CometChatUrlFormatter
} from '@cometchat/chat-uikit-angular' ;
@ Component ({
selector: 'app-formatted-composer' ,
standalone: true ,
imports: [ CometChatMessageComposerComponent ],
template: `
<cometchat-message-composer
[user]="selectedUser"
[textFormatters]="formatters"
(sendButtonClick)="onMessageSent($event)"
></cometchat-message-composer>
`
})
export class FormattedComposerComponent {
selectedUser !: CometChat . User ;
formatters = [
new CometChatMentionsFormatter (),
new CometChatUrlFormatter ()
];
onMessageSent ( message : CometChat . BaseMessage ) : void {
// Message metadata will contain formatter results
const metadata = message . getMetadata ();
console . log ( 'Mentions:' , metadata ?. mentions );
console . log ( 'URLs:' , metadata ?. urls );
}
}
See all 35 lines
Error Handling
The component provides comprehensive error handling through the error event:
import { Component } from '@angular/core' ;
import { CometChat } from '@cometchat/chat-sdk-javascript' ;
import { CometChatMessageComposerComponent } from '@cometchat/chat-uikit-angular' ;
@ Component ({
selector: 'app-error-handling' ,
standalone: true ,
imports: [ CometChatMessageComposerComponent ],
template: `
<cometchat-message-composer
[user]="selectedUser"
(error)="handleError($event)"
></cometchat-message-composer>
`
})
export class ErrorHandlingComponent {
selectedUser !: CometChat . User ;
handleError ( error : CometChat . CometChatException ) : void {
console . error ( 'Composer error:' , error );
switch ( error . code ) {
case 'COMPONENT_ERROR' :
// Handle component-level errors
break ;
case 'COMPOSER_ERROR' :
// Handle message sending errors
break ;
case 'UNKNOWN_ERROR' :
// Handle unexpected errors
break ;
default :
// Handle other errors
break ;
}
}
}
See all 37 lines
Troubleshooting
Issue: Enter key creates line breaks when I want it to send messages
Solution: Set enterKeyBehavior to SendMessage:
import { EnterKeyBehavior } from '@cometchat/chat-uikit-angular' ;
< cometchat - message - composer
[ enterKeyBehavior ] = "EnterKeyBehavior.SendMessage"
> </ cometchat - message - composer >
Issue: I need a compact single-line input
Solution: Use the single-line layout with maxHeight:
< cometchat - message - composer
[ layout ] = "'single-line'"
[ maxHeight ] = "50"
> </ cometchat - message - composer >
Issue: My custom toggle button is gone
Solution: The built-in toggle was removed. Implement your own toggle control as shown in Scenario 3 above.
See Also