The CometChatCollaborativeWhiteboardBubble component renders collaborative whiteboard messages within chat. It displays a banner image, title, subtitle, and an action button that opens the whiteboard in a new fullscreen window.
Overview
The Collaborative Whiteboard Bubble component processes CometChat.CustomMessage objects of type extension_whiteboard to display collaborative whiteboard content:
Message Object Processing : Extracts whiteboard URL from message metadata
Theme-aware Banner Images : Automatically selects light/dark banner images based on current theme
Localized Text : Displays title, subtitle, and button text using localization keys
Sender/Receiver Styling : Supports outgoing (right-aligned) and incoming (left-aligned) visual variants
Action Button : Opens the whiteboard URL in a new fullscreen window
Accessibility : Full keyboard navigation and screen reader support
Basic Usage
Simple Whiteboard Message
import { Component } from '@angular/core' ;
import { CometChat } from '@cometchat/chat-sdk-javascript' ;
import {
CometChatCollaborativeWhiteboardBubbleComponent ,
MessageBubbleAlignment
} from '@cometchat/chat-uikit-angular' ;
@ Component ({
selector: 'app-whiteboard-message' ,
standalone: true ,
imports: [ CometChatCollaborativeWhiteboardBubbleComponent ],
template: `
<cometchat-collaborative-whiteboard-bubble
[message]="whiteboardMessage"
[alignment]="MessageBubbleAlignment.LEFT"
></cometchat-collaborative-whiteboard-bubble>
`
})
export class WhiteboardMessageComponent {
whiteboardMessage !: CometChat . CustomMessage ;
MessageBubbleAlignment = MessageBubbleAlignment ;
}
See all 22 lines
Incoming vs Outgoing Messages
import { Component } from '@angular/core' ;
import { CometChat } from '@cometchat/chat-sdk-javascript' ;
import {
CometChatCollaborativeWhiteboardBubbleComponent ,
MessageBubbleAlignment
} from '@cometchat/chat-uikit-angular' ;
@ Component ({
selector: 'app-message-list' ,
standalone: true ,
imports: [ CometChatCollaborativeWhiteboardBubbleComponent ],
template: `
<!-- Incoming message (left-aligned) -->
<cometchat-collaborative-whiteboard-bubble
[message]="incomingMessage"
[alignment]="MessageBubbleAlignment.LEFT"
></cometchat-collaborative-whiteboard-bubble>
<!-- Outgoing message (right-aligned) -->
<cometchat-collaborative-whiteboard-bubble
[message]="outgoingMessage"
[alignment]="MessageBubbleAlignment.RIGHT"
></cometchat-collaborative-whiteboard-bubble>
`
})
export class MessageListComponent {
incomingMessage !: CometChat . CustomMessage ;
outgoingMessage !: CometChat . CustomMessage ;
MessageBubbleAlignment = MessageBubbleAlignment ;
}
See all 30 lines
With Event Handler
import { Component } from '@angular/core' ;
import { CometChat } from '@cometchat/chat-sdk-javascript' ;
import { CometChatCollaborativeWhiteboardBubbleComponent } from '@cometchat/chat-uikit-angular' ;
@ Component ({
selector: 'app-interactive-whiteboard' ,
standalone: true ,
imports: [ CometChatCollaborativeWhiteboardBubbleComponent ],
template: `
<cometchat-collaborative-whiteboard-bubble
[message]="whiteboardMessage"
(buttonClick)="onWhiteboardOpen($event)"
></cometchat-collaborative-whiteboard-bubble>
`
})
export class InteractiveWhiteboardComponent {
whiteboardMessage !: CometChat . CustomMessage ;
onWhiteboardOpen ( url : string ) : void {
console . log ( 'Whiteboard opened:' , url );
// Custom handling - the component already opens the URL in a new window
}
}
See all 23 lines
Properties
Property Type Default Description messageCometChat.CustomMessagerequired The CometChat.CustomMessage object containing collaborative whiteboard metadata alignmentMessageBubbleAlignmentMessageBubbleAlignment.LEFTThe alignment of the message bubble. LEFT for incoming/receiver messages, RIGHT for outgoing/sender messages disableInteractionbooleanfalseWhen true, disables the action button and other interactive elements within the bubble
Events
Event Payload Type Description buttonClickstringEmitted when the action button is clicked. Contains the whiteboard URL string
The component extracts the whiteboard URL from the following metadata path:
{
"@injected" : {
"extensions" : {
"whiteboard" : {
"board_url" : "https://example.com/whiteboard/456"
}
}
}
}
Advanced Usage
Complete Chat Message Component
import { Component , Input } from '@angular/core' ;
import { CommonModule } from '@angular/common' ;
import { CometChat } from '@cometchat/chat-sdk-javascript' ;
import {
CometChatCollaborativeWhiteboardBubbleComponent ,
MessageBubbleAlignment
} from '@cometchat/chat-uikit-angular' ;
@ Component ({
selector: 'app-whiteboard-chat-message' ,
standalone: true ,
imports: [ CommonModule , CometChatCollaborativeWhiteboardBubbleComponent ],
template: `
<div class="message-container" [class.outgoing]="isOutgoing">
<div class="message-bubble">
<cometchat-collaborative-whiteboard-bubble
[message]="message"
[alignment]="alignment"
(buttonClick)="handleWhiteboardOpen($event)"
></cometchat-collaborative-whiteboard-bubble>
</div>
<div class="message-metadata">
<span class="timestamp">{{ message.getSentAt() * 1000 | date:'short' }}</span>
</div>
</div>
` ,
styles: [ `
.message-container {
display: flex;
flex-direction: column;
margin-bottom: 12px;
max-width: 70%;
}
.message-container.outgoing {
align-self: flex-end;
align-items: flex-end;
}
.message-bubble {
display: inline-block;
}
.message-metadata {
display: flex;
align-items: center;
gap: 6px;
margin-top: 4px;
font-size: 11px;
color: #999;
}
` ]
})
export class WhiteboardChatMessageComponent {
@ Input () message !: CometChat . CustomMessage ;
@ Input () loggedInUserId !: string ;
get isOutgoing () : boolean {
return this . message . getSender (). getUid () === this . loggedInUserId ;
}
get alignment () : MessageBubbleAlignment {
return this . isOutgoing ? MessageBubbleAlignment . RIGHT : MessageBubbleAlignment . LEFT ;
}
handleWhiteboardOpen ( url : string ) : void {
console . log ( 'Whiteboard URL:' , url );
// Additional tracking or custom handling
}
}
See all 70 lines
Message List with Whiteboard Bubbles
import { Component , OnInit } from '@angular/core' ;
import { CommonModule } from '@angular/common' ;
import { CometChat } from '@cometchat/chat-sdk-javascript' ;
import {
CometChatCollaborativeWhiteboardBubbleComponent ,
MessageBubbleAlignment
} from '@cometchat/chat-uikit-angular' ;
@ Component ({
selector: 'app-whiteboard-message-list' ,
standalone: true ,
imports: [ CommonModule , CometChatCollaborativeWhiteboardBubbleComponent ],
template: `
<div class="message-list">
@for (message of messages; track message.getId()) {
<div class="message-wrapper" [class.outgoing]="isOutgoing(message)">
<cometchat-collaborative-whiteboard-bubble
[message]="message"
[alignment]="getAlignment(message)"
(buttonClick)="onWhiteboardOpen($event)"
></cometchat-collaborative-whiteboard-bubble>
</div>
}
</div>
` ,
styles: [ `
.message-list {
display: flex;
flex-direction: column;
gap: 8px;
padding: 16px;
}
.message-wrapper {
display: flex;
max-width: 70%;
}
.message-wrapper.outgoing {
align-self: flex-end;
}
` ]
})
export class WhiteboardMessageListComponent implements OnInit {
messages : CometChat . CustomMessage [] = [];
loggedInUser !: CometChat . User ;
async ngOnInit () : Promise < void > {
this . loggedInUser = await CometChat . getLoggedinUser ();
}
isOutgoing ( message : CometChat . CustomMessage ) : boolean {
return message . getSender (). getUid () === this . loggedInUser ?. getUid ();
}
getAlignment ( message : CometChat . CustomMessage ) : MessageBubbleAlignment {
return this . isOutgoing ( message )
? MessageBubbleAlignment . RIGHT
: MessageBubbleAlignment . LEFT ;
}
onWhiteboardOpen ( url : string ) : void {
console . log ( 'Opening whiteboard:' , url );
}
}
See all 65 lines
Customization
Styling with CSS Variables
The Collaborative Whiteboard Bubble component uses CSS variables exclusively for easy customization:
/* Custom whiteboard bubble styling */
cometchat-collaborative-whiteboard-bubble {
/* Spacing */
--cometchat-spacing-1 : 4 px ;
--cometchat-spacing-2 : 8 px ;
--cometchat-spacing-3 : 12 px ;
--cometchat-spacing-4 : 16 px ;
/* Typography */
--cometchat-font-heading4-medium : 500 16 px 'Inter' ;
--cometchat-font-body-regular : 400 14 px 'Inter' ;
--cometchat-font-button-medium : 500 14 px 'Inter' ;
/* Colors - Incoming messages */
--cometchat-background-color-01 : #FFFFFF ;
--cometchat-background-color-02 : #F5F5F5 ;
--cometchat-text-color-primary : #141414 ;
--cometchat-text-color-secondary : #666666 ;
/* Colors - Outgoing messages */
--cometchat-primary-button-background : #6852D6 ;
--cometchat-primary-button-text : #FFFFFF ;
/* Border radius */
--cometchat-radius-2 : 8 px ;
--cometchat-radius-3 : 12 px ;
/* Border colors */
--cometchat-border-color-light : #E0E0E0 ;
}
See all 30 lines
Available CSS Variables
Variable Purpose Default --cometchat-spacing-1 to --cometchat-spacing-4Padding, margin, gap 4px to 16px--cometchat-font-heading4-mediumTitle font 500 16px Roboto--cometchat-font-body-regularSubtitle font 400 14px Roboto--cometchat-font-button-mediumButton text font 500 14px Roboto--cometchat-background-color-01Bubble background #FFFFFF--cometchat-background-color-02Body section background #F5F5F5--cometchat-text-color-primaryTitle color #141414--cometchat-text-color-secondarySubtitle color #666666--cometchat-primary-button-backgroundButton background #6852D6--cometchat-primary-button-textButton text color #FFFFFF--cometchat-radius-2Border radius 8px--cometchat-border-color-lightBorder color #E0E0E0
Custom Color Schemes
/* Blue theme */
.theme-blue cometchat-collaborative-whiteboard-bubble {
--cometchat-primary-button-background : #1976D2 ;
--cometchat-primary-color : #1976D2 ;
}
/* Green theme */
.theme-green cometchat-collaborative-whiteboard-bubble {
--cometchat-primary-button-background : #4CAF50 ;
--cometchat-primary-color : #4CAF50 ;
}
/* Dark theme */
[ data-theme = "dark" ] cometchat-collaborative-whiteboard-bubble {
--cometchat-background-color-01 : #1E1E1E ;
--cometchat-background-color-02 : #2C2C2C ;
--cometchat-text-color-primary : #FFFFFF ;
--cometchat-text-color-secondary : #B0B0B0 ;
--cometchat-border-color-light : #404040 ;
}
See all 20 lines
/* Custom button styling */
:: ng-deep .cometchat-collaborative-whiteboard-bubble__button {
background : linear-gradient ( 135 deg , #667eea 0 % , #764ba2 100 % );
border-radius : 20 px ;
padding : 10 px 20 px ;
font-weight : 600 ;
box-shadow : 0 2 px 4 px rgba ( 0 , 0 , 0 , 0.1 );
transition : transform 0.2 s , box-shadow 0.2 s ;
}
:: ng-deep .cometchat-collaborative-whiteboard-bubble__button:hover:not ( :disabled ) {
transform : translateY ( -1 px );
box-shadow : 0 4 px 8 px rgba ( 0 , 0 , 0 , 0.15 );
}
See all 14 lines
Accessibility
The Collaborative Whiteboard Bubble component is fully accessible and follows WCAG 2.1 Level AA guidelines.
WCAG 2.1 Compliance
✅ 1.1.1 Non-text Content (Level A) : Banner image has empty alt attribute (decorative)
✅ 1.3.1 Info and Relationships (Level A) : Proper semantic structure with button element
✅ 2.1.1 Keyboard (Level A) : All functionality available via keyboard
✅ 2.4.7 Focus Visible (Level AA) : Clear focus indicators on action button
✅ 4.1.2 Name, Role, Value (Level A) : Action button has accessible name via aria-label
Keyboard Support
Key Action Context TabNavigate to action button When component is in focus order Shift + TabNavigate backwards When button is focused EnterActivate button When button is focused SpaceActivate button When button is focused
ARIA Attributes
Attribute Element Value Purpose aria-labelAction button Localized button text Provides accessible name altBanner image Empty string Marks image as decorative
Screen Reader Behavior
Screen readers announce the component with:
Banner image : Skipped (decorative)
Title : “Collaborative Whiteboard” (or localized equivalent)
Subtitle : “Open whiteboard to draw together” (or localized equivalent)
Button : “Open Whiteboard, button” (or localized equivalent)
Best Practices
Always provide the complete CometChat.CustomMessage object to ensure the whiteboard URL is correctly extracted from metadata.
The component expects the whiteboard URL at metadata["@injected"]["extensions"]["whiteboard"]["board_url"]. Ensure your message objects have this structure.
Use the alignment property to distinguish between incoming and outgoing messages for proper visual styling.
Handle the buttonClick event if you need custom behavior beyond opening the URL in a new window.
The action button is automatically disabled when the whiteboard URL is missing or empty.
The component automatically selects the appropriate banner image based on the current theme (light/dark).
CometChatCollaborativeDocumentBubble : Displays collaborative document messages
CometChatFileBubble : Displays file attachment messages
CometChatMessageBubble : Parent component for message bubbles
CometChatMessageList : Displays lists of messages
Technical Details
Standalone Component : Can be imported and used independently
Change Detection : Uses OnPush change detection strategy for optimal performance
Dependencies :
Angular CommonModule
CometChat SDK for message types
TranslatePipe for localization
BEM CSS : Follows Block Element Modifier naming convention
Accessibility : WCAG 2.1 Level AA compliant