The CometChatAudioBubble component is a sophisticated audio message display component that renders audio messages with real-time waveform visualization and playback controls. It serves as the primary content renderer for audio-based messages in the CometChat Angular UIKit, handling everything from single audio display to complex multi-audio layouts with expand/collapse behavior.
Overview
The Audio Bubble component renders audio messages with waveform visualization and playback controls while maintaining visual consistency with the design system and ensuring full accessibility:
Message Object Processing : Extracts attachments and metadata from CometChat.MediaMessage objects
Single Audio Display : Waveform visualization with play/pause button and time display
Real-time Waveform : Visual representation of audio amplitude with seek support via WaveSurfer
Playback Controls : Play/pause with single audio player policy (only one audio plays at a time)
Time Display : Current time / duration in M:SS format
Download with Progress : Circular progress indicator with cancellation support
Caption Support : Renders captions using TextMessageBubbleComponent
Dual Styling : Supports sender (outgoing) and receiver (incoming) visual variants
Accessibility : Full keyboard navigation and screen reader support
Basic Usage
Simple Audio Message
import { Component } from '@angular/core' ;
import { CometChat } from '@cometchat/chat-sdk-javascript' ;
import { CometChatAudioBubbleComponent , MessageBubbleAlignment } from '@cometchat/chat-uikit-angular' ;
@ Component ({
selector: 'app-chat-message' ,
standalone: true ,
imports: [ CometChatAudioBubbleComponent ],
template: `
<cometchat-audio-bubble
[message]="audioMessage"
[alignment]="MessageBubbleAlignment.LEFT"
></cometchat-audio-bubble>
`
})
export class ChatMessageComponent {
audioMessage !: CometChat . MediaMessage ;
MessageBubbleAlignment = MessageBubbleAlignment ;
}
See all 19 lines
Incoming vs Outgoing Messages
import { Component } from '@angular/core' ;
import { CometChat } from '@cometchat/chat-sdk-javascript' ;
import { CometChatAudioBubbleComponent , MessageBubbleAlignment } from '@cometchat/chat-uikit-angular' ;
@ Component ({
selector: 'app-message-list' ,
standalone: true ,
imports: [ CometChatAudioBubbleComponent ],
template: `
<!-- Incoming message (left-aligned) -->
<cometchat-audio-bubble
[message]="incomingMessage"
[alignment]="MessageBubbleAlignment.LEFT"
></cometchat-audio-bubble>
<!-- Outgoing message (right-aligned) -->
<cometchat-audio-bubble
[message]="outgoingMessage"
[alignment]="MessageBubbleAlignment.RIGHT"
></cometchat-audio-bubble>
`
})
export class MessageListComponent {
incomingMessage !: CometChat . MediaMessage ;
outgoingMessage !: CometChat . MediaMessage ;
MessageBubbleAlignment = MessageBubbleAlignment ;
}
See all 27 lines
With Event Handlers
import { Component } from '@angular/core' ;
import { CometChat } from '@cometchat/chat-sdk-javascript' ;
import { CometChatAudioBubbleComponent , AudioAttachment } from '@cometchat/chat-uikit-angular' ;
@ Component ({
selector: 'app-interactive-message' ,
standalone: true ,
imports: [ CometChatAudioBubbleComponent ],
template: `
<cometchat-audio-bubble
[message]="audioMessage"
(playStateChange)="onPlayStateChange($event)"
(downloadStart)="onDownloadStart($event)"
(downloadComplete)="onDownloadComplete($event)"
(downloadError)="onDownloadError($event)"
></cometchat-audio-bubble>
`
})
export class InteractiveMessageComponent {
audioMessage !: CometChat . MediaMessage ;
onPlayStateChange ( event : { isPlaying : boolean ; attachment : AudioAttachment }) : void {
console . log ( 'Playback state changed:' , event . isPlaying ? 'Playing' : 'Paused' );
}
onDownloadStart ( attachment : AudioAttachment ) : void {
console . log ( 'Download started:' , attachment . name );
}
onDownloadComplete ( attachment : AudioAttachment ) : void {
console . log ( 'Download completed:' , attachment . name );
}
onDownloadError ( event : { attachment : AudioAttachment ; error : Error }) : void {
console . error ( 'Download failed:' , event . error . message );
}
}
See all 37 lines
Properties
Property Type Default Description messageCometChat.MediaMessagerequired The CometChat.MediaMessage object to render. Contains audio attachments, metadata, and sender information alignmentMessageBubbleAlignmentMessageBubbleAlignment.LEFTThe alignment of the message bubble. LEFT for incoming/receiver messages, RIGHT for outgoing/sender messages
Events
Event Payload Type Description playStateChange{ isPlaying: boolean; attachment: AudioAttachment }Emitted when playback state changes (play/pause). Contains the current playing state and the associated attachment downloadStartAudioAttachmentEmitted when download begins for an audio file downloadCompleteAudioAttachmentEmitted when download completes successfully downloadError{ attachment: AudioAttachment; error: Error }Emitted when download fails. Contains the attachment and error details
Advanced Usage
Single Audio Message
The component displays single audio messages with waveform visualization and playback controls:
import { Component } from '@angular/core' ;
import { CometChat } from '@cometchat/chat-sdk-javascript' ;
import { CometChatAudioBubbleComponent } from '@cometchat/chat-uikit-angular' ;
@ Component ({
selector: 'app-single-audio' ,
standalone: true ,
imports: [ CometChatAudioBubbleComponent ],
template: `
<cometchat-audio-bubble
[message]="singleAudioMessage"
></cometchat-audio-bubble>
`
})
export class SingleAudioComponent {
singleAudioMessage !: CometChat . MediaMessage ;
}
See all 17 lines
Single Audio Features:
Play/pause button on the left
Real-time waveform visualization with seek support
Current time / duration display (M:SS format)
Download button on the right
Fixed width of 240px for consistent layout
Audios with Captions
The component automatically renders captions using the TextMessageBubbleComponent:
import { Component } from '@angular/core' ;
import { CometChat } from '@cometchat/chat-sdk-javascript' ;
import { CometChatAudioBubbleComponent } from '@cometchat/chat-uikit-angular' ;
@ Component ({
selector: 'app-captioned-audio' ,
standalone: true ,
imports: [ CometChatAudioBubbleComponent ],
template: `
<cometchat-audio-bubble
[message]="captionedAudioMessage"
></cometchat-audio-bubble>
`
})
export class CaptionedAudioComponent {
captionedAudioMessage !: CometChat . MediaMessage ;
// Message with caption:
// message.getText() returns "Check out this podcast episode!"
}
See all 20 lines
Caption Features:
Displays below the audio(s)
Supports rich text formatting (bold, italic, etc.)
Supports @mentions with click events
Supports URLs with click events
Supports read more/less for long captions
Inherits alignment from parent bubble
The component uses an embedded WaveSurfer library for real-time waveform visualization:
import { Component } from '@angular/core' ;
import { CometChat } from '@cometchat/chat-sdk-javascript' ;
import { CometChatAudioBubbleComponent , MessageBubbleAlignment } from '@cometchat/chat-uikit-angular' ;
@ Component ({
selector: 'app-waveform-demo' ,
standalone: true ,
imports: [ CometChatAudioBubbleComponent ],
template: `
<!-- Sender variant: white progress, neutral-500 wave -->
<cometchat-audio-bubble
[message]="audioMessage"
[alignment]="MessageBubbleAlignment.RIGHT"
></cometchat-audio-bubble>
<!-- Receiver variant: primary color progress, extended-primary-300 wave -->
<cometchat-audio-bubble
[message]="audioMessage"
[alignment]="MessageBubbleAlignment.LEFT"
></cometchat-audio-bubble>
`
})
export class WaveformDemoComponent {
audioMessage !: CometChat . MediaMessage ;
MessageBubbleAlignment = MessageBubbleAlignment ;
}
See all 26 lines
Waveform Features:
Real-time audio amplitude visualization
Click to seek to any position
Drag to seek with real-time updates
Different colors for played vs unplayed portions
Sender variant: white progress, neutral-500 wave color
Receiver variant: primary color progress, extended-primary-300 wave color
Fixed width of 140px within the audio bubble
Height of 16px for waveform bars
Download with Progress
The component provides download functionality with a circular progress indicator:
import { Component } from '@angular/core' ;
import { CometChat } from '@cometchat/chat-sdk-javascript' ;
import { CometChatAudioBubbleComponent , AudioAttachment } from '@cometchat/chat-uikit-angular' ;
@ Component ({
selector: 'app-download-demo' ,
standalone: true ,
imports: [ CometChatAudioBubbleComponent ],
template: `
<cometchat-audio-bubble
[message]="audioMessage"
(downloadStart)="onDownloadStart($event)"
(downloadComplete)="onDownloadComplete($event)"
(downloadError)="onDownloadError($event)"
></cometchat-audio-bubble>
`
})
export class DownloadDemoComponent {
audioMessage !: CometChat . MediaMessage ;
onDownloadStart ( attachment : AudioAttachment ) : void {
console . log ( 'Starting download:' , attachment . name );
}
onDownloadComplete ( attachment : AudioAttachment ) : void {
console . log ( 'Download complete:' , attachment . name );
// File is automatically saved with original filename
}
onDownloadError ( event : { attachment : AudioAttachment ; error : Error }) : void {
console . error ( 'Download failed:' , event . error . message );
}
}
See all 33 lines
Download Features:
Circular progress indicator showing completion percentage (0-100%)
Cancel button in the center of the progress circle
Automatic file download with original filename on completion
Error handling with event emission
Sender variant: white download icon and progress
Receiver variant: primary color download icon and progress
Single Audio Player Policy
The component implements a single audio player policy - only one audio can play at a time across all audio bubbles:
import { Component } from '@angular/core' ;
import { CometChat } from '@cometchat/chat-sdk-javascript' ;
import { CometChatAudioBubbleComponent , AudioAttachment } from '@cometchat/chat-uikit-angular' ;
@ Component ({
selector: 'app-audio-list' ,
standalone: true ,
imports: [ CometChatAudioBubbleComponent ],
template: `
@for (message of audioMessages; track message.getId()) {
<cometchat-audio-bubble
[message]="message"
(playStateChange)="onPlayStateChange($event)"
></cometchat-audio-bubble>
}
`
})
export class AudioListComponent {
audioMessages : CometChat . MediaMessage [] = [];
onPlayStateChange ( event : { isPlaying : boolean ; attachment : AudioAttachment }) : void {
// When one audio starts playing, any other playing audio is automatically paused
if ( event . isPlaying ) {
console . log ( 'Now playing:' , event . attachment . name );
}
}
}
See all 27 lines
Single Player Policy Features:
Only one audio plays at a time across all audio bubbles
Starting a new audio automatically pauses any currently playing audio
Global singleton tracks the currently playing audio
Automatic cleanup on component destruction
Time Display
The component displays current playback time and total duration:
// Time format examples:
// 0 seconds → "0:00"
// 45 seconds → "0:45"
// 125 seconds (2 min 5 sec) → "2:05"
// 3665 seconds (1 hr 1 min 5 sec) → "61:05"
Time Display Features:
Format: “M:SS / M:SS” (current / total)
Updates continuously during playback
Updates immediately on seek via waveform
Sender variant: white text color
Receiver variant: neutral-600 text color
Customization
Styling with CSS Variables
The Audio Bubble component uses CSS variables exclusively for easy customization:
/* Custom audio bubble styling */
cometchat-audio-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-caption1-regular : 400 12 px 'Inter' ;
--cometchat-font-caption1-bold : 600 12 px 'Inter' ;
/* Colors - Incoming messages */
--cometchat-neutral-color-300 : #E0E0E0 ;
--cometchat-neutral-color-600 : #666666 ;
--cometchat-primary-color : #6852D6 ;
--cometchat-extended-primary-color-300 : #B8A8F0 ;
/* Colors - Outgoing messages */
--cometchat-primary-button-background : #6852D6 ;
--cometchat-static-white : #FFFFFF ;
--cometchat-neutral-color-500 : #9E9E9E ;
/* Border radius */
--cometchat-radius-3 : 12 px ;
--cometchat-radius-max : 1000 px ;
}
See all 27 lines
Available CSS Variables
Variable Purpose Default --cometchat-spacing-1 to --cometchat-spacing-4Padding, margin, gap 4px to 16px--cometchat-font-caption1-regularTime display font 400 12px Roboto--cometchat-font-caption1-boldExpand indicator font 600 12px Roboto--cometchat-primary-colorReceiver waveform progress, download icon #6852D6--cometchat-extended-primary-color-300Receiver waveform wave color #B8A8F0--cometchat-neutral-color-300Receiver bubble background #E0E0E0--cometchat-neutral-color-500Sender waveform wave color #9E9E9E--cometchat-neutral-color-600Receiver time text color #666666--cometchat-static-whiteSender waveform progress, text, icons #FFFFFF--cometchat-primary-button-backgroundSender bubble background #6852D6--cometchat-radius-3Bubble border radius 12px--cometchat-radius-maxPlay button, expand indicator radius 1000px (circular)
Custom Color Schemes
/* Blue theme for incoming messages */
.theme-blue cometchat-audio-bubble {
--cometchat-neutral-color-300 : #E3F2FD ;
--cometchat-primary-color : #1976D2 ;
--cometchat-extended-primary-color-300 : #90CAF9 ;
}
/* Green theme for outgoing messages */
.theme-green cometchat-audio-bubble {
--cometchat-primary-button-background : #4CAF50 ;
}
/* Dark theme */
[ data-theme = "dark" ] cometchat-audio-bubble {
--cometchat-neutral-color-300 : #2C2C2C ;
--cometchat-neutral-color-600 : #B0B0B0 ;
}
See all 17 lines
/* Custom play/pause button styling */
:: ng-deep .cometchat-audio-bubble__play-button ,
:: ng-deep .cometchat-audio-bubble__pause-button {
width : 36 px ;
height : 36 px ;
border-radius : 50 % ;
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-audio-bubble__play-button:hover ,
:: ng-deep .cometchat-audio-bubble__pause-button:hover {
transform : scale ( 1.05 );
box-shadow : 0 4 px 8 px rgba ( 0 , 0 , 0 , 0.15 );
}
See all 15 lines
Custom Expand Indicator Styling
/* Custom expand indicator button */
:: ng-deep .cometchat-audio-bubble__expand-indicator {
background : linear-gradient ( 135 deg , #667eea 0 % , #764ba2 100 % );
padding : 6 px 12 px ;
border-radius : 16 px ;
font-weight : 700 ;
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-audio-bubble__expand-indicator:hover {
transform : translateY ( -1 px );
box-shadow : 0 4 px 8 px rgba ( 0 , 0 , 0 , 0.15 );
}
See all 14 lines
Custom Download Progress Styling
/* Custom download progress indicator */
:: ng-deep .cometchat-audio-bubble__download-progress {
position : relative ;
}
:: ng-deep .cometchat-audio-bubble__progress-bg {
stroke : rgba ( 255 , 255 , 255 , 0.3 );
stroke-width : 2 ;
fill : none ;
}
:: ng-deep .cometchat-audio-bubble__progress-fg {
stroke : currentColor ;
stroke-width : 2 ;
fill : none ;
stroke-linecap : round ;
transform : rotate ( -90 deg );
transform-origin : center ;
transition : stroke-dasharray 0.3 s ease ;
}
See all 20 lines
Accessibility
The Audio Bubble component is fully accessible and follows WCAG 2.1 Level AA guidelines.
WCAG 2.1 Compliance
The component meets the following WCAG 2.1 Level AA success criteria:
✅ 1.1.1 Non-text Content (Level A) : All controls have descriptive ARIA labels
✅ 1.3.1 Info and Relationships (Level A) : Proper semantic structure with buttons
✅ 2.1.1 Keyboard (Level A) : All functionality available via keyboard
✅ 2.4.7 Focus Visible (Level AA) : Clear focus indicators on all interactive elements
✅ 4.1.2 Name, Role, Value (Level A) : All elements have accessible names and roles
Keyboard Support
Key Action Context TabNavigate to play/pause button When audio bubble is focused Shift + TabNavigate backwards When any control is focused EnterToggle play/pause When play/pause button is focused SpaceToggle play/pause When play/pause button is focused EnterStart download When download button is focused EnterCancel download When cancel button is focused Arrow Left/RightSeek audio When waveform is focused
ARIA Attributes
The component automatically applies appropriate ARIA attributes:
Attribute Element Value Purpose aria-labelPlay button "Play audio"Describes the play action aria-labelPause button "Pause audio"Describes the pause action aria-labelDownload button "Download audio"Describes the download action aria-labelCancel button "Cancel download"Describes the cancel action aria-labelWaveform "Audio waveform, use arrow keys to seek"Describes waveform interaction
Screen Reader Behavior
Screen readers announce the audio bubble with:
Play button : “Button, Play audio”
Pause button : “Button, Pause audio”
Download button : “Button, Download audio”
Expand indicator : “Button, Show 3 more, collapsed”
Collapse button : “Button, Show less, expanded”
State changes : Announces playback state changes
Accessibility Best Practices
The component automatically handles all accessibility requirements. No additional ARIA attributes or keyboard handling is needed.
When handling playStateChange events, ensure your custom actions maintain accessibility by managing focus appropriately.
All interactive elements (play/pause, download, expand/collapse, waveform) are keyboard accessible and have visible focus indicators.
Best Practices
Always provide the complete CometChat.MediaMessage object to ensure all features (attachments, captions, metadata) work correctly.
The component expects audio attachments with valid URLs. Ensure your message objects have properly formatted attachment data.
Use the alignment property to distinguish between incoming and outgoing messages for proper visual styling.
Handle playStateChange events to track analytics or perform custom actions when audio playback state changes.
The component does NOT open a modal or fullscreen view. Expansion happens inline within the message bubble.
The component handles missing or invalid data gracefully, displaying error states without breaking the UI.
The single audio player policy ensures a good user experience - only one audio plays at a time across all audio bubbles.
CometChatTextBubble : Used for rendering captions in audio messages
CometChatFileBubble : Displays file messages with download functionality
CometChatImageBubble : Displays image messages with grid layouts and gallery
CometChatVideoBubble : Displays video messages with thumbnails and player
CometChatMessageBubble : Uses Audio Bubble as the content view for audio messages
CometChatMessageList : Displays lists of messages including audio bubbles
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
CometChatTextBubbleComponent for captions
Embedded WaveSurfer library for waveform visualization
Bundle Size : Minimal footprint (~15KB including WaveSurfer)
BEM CSS : Follows Block Element Modifier naming convention
Accessibility : WCAG 2.1 Level AA compliant
Optimization Strategies
Change Detection:
Uses OnPush strategy to minimize unnecessary re-renders
Only updates when inputs change or events are emitted
WaveSurfer Initialization:
WaveSurfer instances are created lazily (only when visible)
Instances are properly destroyed on component destruction
Audio decoding happens asynchronously to avoid blocking UI
Single Audio Player Policy:
Global singleton ensures only one audio plays at a time
Reduces memory usage and improves performance
Automatic cleanup when components are destroyed
Download Progress:
Uses ReadableStream for efficient progress tracking
Supports cancellation via AbortController
Progress updates are throttled to avoid excessive re-renders
The component uses OnPush change detection. Ensure message objects are immutable for optimal performance.
WaveSurfer instances are created lazily. Only visible audio attachments have active waveform visualizations.
Avoid frequently changing the message input. Each change triggers re-processing of attachments and WaveSurfer re-initialization.
The embedded WaveSurfer library is optimized for the audio bubble use case with minimal configuration.