Skip to main content
The CometChatVideoBubble component is a sophisticated video message display component that renders video messages with advanced layout capabilities. It serves as the primary content renderer for video-based messages in the CometChat Angular UIKit, handling everything from single video display to complex multi-video grid layouts with fullscreen playback capabilities.

Overview

The Video Bubble component renders video messages with advanced layout capabilities while maintaining visual consistency with the design system and ensuring full accessibility:
  • Message Object Processing: Extracts attachments and metadata from CometChat.MediaMessage objects
  • Single Video Display: Thumbnail with play button overlay and duration badge
  • Fullscreen Player: Modal video player with standard HTML5 controls
  • Duration Formatting: Displays video length in M:SS or H:MM:SS format
  • Caption Support: Renders captions using TextMessageBubbleComponent
  • Lazy Loading: Performance optimization for thumbnail and video loading
  • Dual Styling: Supports sender (outgoing) and receiver (incoming) visual variants
  • Accessibility: Full keyboard navigation and screen reader support
Live Preview — Default video bubble preview. Open in Storybook ↗

Basic Usage

Simple Video Message

import { Component } from '@angular/core';
import { CometChat } from '@cometchat/chat-sdk-javascript';
import { CometChatVideoBubbleComponent, MessageBubbleAlignment } from '@cometchat/chat-uikit-angular';

@Component({
  selector: 'app-chat-message',
  standalone: true,
  imports: [CometChatVideoBubbleComponent],
  template: `
    <cometchat-video-bubble
      [message]="videoMessage"
      [alignment]="MessageBubbleAlignment.LEFT"
    ></cometchat-video-bubble>
  `
})
export class ChatMessageComponent {
  videoMessage!: CometChat.MediaMessage;
  MessageBubbleAlignment = MessageBubbleAlignment;
}

Incoming vs Outgoing Messages

import { Component } from '@angular/core';
import { CometChat } from '@cometchat/chat-sdk-javascript';
import { CometChatVideoBubbleComponent, MessageBubbleAlignment } from '@cometchat/chat-uikit-angular';

@Component({
  selector: 'app-message-list',
  standalone: true,
  imports: [CometChatVideoBubbleComponent],
  template: `
    <!-- Incoming message (left-aligned) -->
    <cometchat-video-bubble
      [message]="incomingMessage"
      [alignment]="MessageBubbleAlignment.LEFT"
    ></cometchat-video-bubble>

    <!-- Outgoing message (right-aligned) -->
    <cometchat-video-bubble
      [message]="outgoingMessage"
      [alignment]="MessageBubbleAlignment.RIGHT"
    ></cometchat-video-bubble>
  `
})
export class MessageListComponent {
  incomingMessage!: CometChat.MediaMessage;
  outgoingMessage!: CometChat.MediaMessage;
  MessageBubbleAlignment = MessageBubbleAlignment;
}

With Event Handlers

import { Component } from '@angular/core';
import { CometChat } from '@cometchat/chat-sdk-javascript';
import { CometChatVideoBubbleComponent, MediaAttachment } from '@cometchat/chat-uikit-angular';

@Component({
  selector: 'app-interactive-message',
  standalone: true,
  imports: [CometChatVideoBubbleComponent],
  template: `
    <cometchat-video-bubble
      [message]="videoMessage"
      (videoClick)="onVideoClick($event)"
      (playerOpen)="onPlayerOpen()"
      (playerClose)="onPlayerClose()"
    ></cometchat-video-bubble>
  `
})
export class InteractiveMessageComponent {
  videoMessage!: CometChat.MediaMessage;

  onVideoClick(event: { attachment: MediaAttachment; index: number }): void {
    console.log('Video clicked:', event.attachment.url, 'at index:', event.index);
    // Handle video click - player viewer opens automatically
  }

  onPlayerOpen(): void {
    console.log('Video player opened');
    // Track analytics or perform other actions
  }

  onPlayerClose(): void {
    console.log('Video player closed');
    // Track analytics or perform other actions
  }
}

Properties

PropertyTypeDefaultDescription
messageCometChat.MediaMessagerequiredThe CometChat.MediaMessage object to render. Contains video attachments, metadata, and sender information
alignmentMessageBubbleAlignmentMessageBubbleAlignment.LEFTThe alignment of the message bubble. LEFT for incoming/receiver messages, RIGHT for outgoing/sender messages

Events

EventPayload TypeDescription
videoClick{ attachment: MediaAttachment; index: number }Emitted when a video thumbnail is clicked. Contains the clicked attachment object and its index in the attachments array
playerOpenvoidEmitted when the fullscreen video player is opened
playerClosevoidEmitted when the fullscreen video player is closed

Advanced Usage

Single Video Message

The component displays single video messages with thumbnail, play button, and duration badge:
import { Component } from '@angular/core';
import { CometChat } from '@cometchat/chat-sdk-javascript';
import { CometChatVideoBubbleComponent } from '@cometchat/chat-uikit-angular';

@Component({
  selector: 'app-single-video',
  standalone: true,
  imports: [CometChatVideoBubbleComponent],
  template: `
    <cometchat-video-bubble
      [message]="singleVideoMessage"
    ></cometchat-video-bubble>
  `
})
export class SingleVideoComponent {
  singleVideoMessage!: CometChat.MediaMessage;
}
Single Video Features:
  • Thumbnail image display (if available)
  • Play button overlay centered on thumbnail
  • Duration badge showing video length (e.g., “2:05” or “1:01:05”)
  • Lazy loading for thumbnail
  • Click to open fullscreen video player
  • ARIA label for accessibility

Videos with Captions

The component automatically renders captions using the TextMessageBubbleComponent:
import { Component } from '@angular/core';
import { CometChat } from '@cometchat/chat-sdk-javascript';
import { CometChatVideoBubbleComponent } from '@cometchat/chat-uikit-angular';

@Component({
  selector: 'app-captioned-video',
  standalone: true,
  imports: [CometChatVideoBubbleComponent],
  template: `
    <cometchat-video-bubble
      [message]="captionedVideoMessage"
    ></cometchat-video-bubble>
  `
})
export class CaptionedVideoComponent {
  captionedVideoMessage!: CometChat.MediaMessage;
  
  // Message with caption in metadata:
  // message.getText() returns "Check out this amazing tutorial!"
  // OR
  // message.getData()?.text returns "Check out this amazing tutorial!"
}
Caption Features:
  • Displays below the video(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

Fullscreen Video Player

The component includes an integrated fullscreen video player with standard HTML5 controls:
import { Component } from '@angular/core';
import { CometChat } from '@cometchat/chat-sdk-javascript';
import { CometChatVideoBubbleComponent } from '@cometchat/chat-uikit-angular';

@Component({
  selector: 'app-player-demo',
  standalone: true,
  imports: [CometChatVideoBubbleComponent],
  template: `
    <cometchat-video-bubble
      [message]="videoMessage"
      (playerOpen)="onPlayerOpen()"
      (playerClose)="onPlayerClose()"
    ></cometchat-video-bubble>
  `
})
export class PlayerDemoComponent {
  videoMessage!: CometChat.MediaMessage;

  onPlayerOpen(): void {
    console.log('Video player opened - track analytics');
    // Body scroll is automatically prevented
  }

  onPlayerClose(): void {
    console.log('Video player closed - track analytics');
    // Body scroll is automatically restored
    // Video playback is automatically stopped
  }
}
Video Player Features:
  • Fullscreen modal overlay
  • HTML5 video element with standard controls:
    • Play/Pause button
    • Seek bar for navigation
    • Volume controls
    • Fullscreen toggle
    • Current time / Duration display
  • Navigation controls for multiple videos (previous/next buttons)
  • Video counter (e.g., “2 of 5”)
  • Close button
  • Keyboard navigation:
    • Escape - Close player
  • Click backdrop to close
  • Focus trap for accessibility
  • Body scroll prevention while open
  • Automatic video stop on close

Duration Formatting

The component automatically formats video durations:
// Duration examples:
// 45 seconds → "0:45"
// 125 seconds (2 min 5 sec) → "2:05"
// 3665 seconds (1 hr 1 min 5 sec) → "1:01:05"
Duration Display:
  • Shows as “M:SS” for videos under 1 hour
  • Shows as “H:MM:SS” for videos 1 hour or longer
  • Positioned in corner of video thumbnail
  • Uses CSS variables for styling

Customization

Styling with CSS Variables

The Video Bubble component uses CSS variables exclusively for easy customization:
/* Custom video bubble styling */
cometchat-video-bubble {
  /* Spacing */
  --cometchat-spacing-1: 4px;
  --cometchat-spacing-2: 8px;
  --cometchat-spacing-3: 12px;
  --cometchat-spacing-4: 16px;

  /* Border radius */
  --cometchat-radius-2: 8px;
  --cometchat-radius-3: 12px;

  /* Colors - Incoming messages */
  --cometchat-background-color-02: #F5F5F5;
  --cometchat-border-color-light: #E0E0E0;

  /* Colors - Outgoing messages */
  --cometchat-primary-button-background: #6852D6;

  /* Play button overlay */
  --cometchat-primary-color: #6852D6;
  --cometchat-static-white: #FFFFFF;

  /* Duration badge */
  --cometchat-font-caption1-regular: 400 12px 'Roboto';
  --cometchat-text-color-white: #FFFFFF;

  /* Overflow overlay */
  --cometchat-font-heading2-bold: 600 20px 'Roboto';
}

Available CSS Variables

VariablePurposeDefault
--cometchat-spacing-1Grid gap, padding4px
--cometchat-spacing-2 to --cometchat-spacing-4Various spacing8px to 16px
--cometchat-radius-2Thumbnail border radius8px
--cometchat-radius-3Bubble border radius12px
--cometchat-background-color-02Incoming bubble background#F5F5F5
--cometchat-primary-button-backgroundOutgoing bubble background#6852D6
--cometchat-primary-colorPlay button color#6852D6
--cometchat-border-color-lightBorder color#E0E0E0
--cometchat-text-color-whiteDuration badge text#FFFFFF
--cometchat-static-whitePlay button icon#FFFFFF
--cometchat-font-caption1-regularDuration badge font400 12px Roboto
--cometchat-font-heading2-boldOverflow text font600 20px Roboto

Custom Color Schemes

/* Blue theme for incoming messages */
.theme-blue cometchat-video-bubble {
  --cometchat-background-color-02: #E3F2FD;
  --cometchat-border-color-light: #90CAF9;
}

/* Green theme for outgoing messages */
.theme-green cometchat-video-bubble {
  --cometchat-primary-button-background: #4CAF50;
  --cometchat-primary-color: #4CAF50;
}

/* Dark theme */
[data-theme="dark"] cometchat-video-bubble {
  --cometchat-background-color-02: #2C2C2C;
  --cometchat-border-color-light: #404040;
}

Custom Play Button Styling

/* Custom play button overlay */
::ng-deep .cometchat-video-bubble__play-overlay {
  background: rgba(0, 0, 0, 0.6);
  border-radius: 50%;
  width: 64px;
  height: 64px;
}

::ng-deep .cometchat-video-bubble__play-icon {
  width: 32px;
  height: 32px;
  filter: drop-shadow(0 2px 4px rgba(0, 0, 0, 0.3));
}

Custom Duration Badge Styling

/* Custom duration badge */
::ng-deep .cometchat-video-bubble__duration-badge {
  background: rgba(0, 0, 0, 0.8);
  border-radius: 4px;
  padding: 4px 8px;
  bottom: 8px;
  right: 8px;
}

::ng-deep .cometchat-video-bubble__duration-text {
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.5px;
}

Custom Video Player Styling

/* Custom fullscreen viewer backdrop */
::ng-deep .cometchat-fullscreen-viewer__backdrop {
  background: rgba(0, 0, 0, 0.95);
}

/* Custom video element */
::ng-deep .cometchat-fullscreen-viewer__media video {
  max-width: 90vw;
  max-height: 80vh;
  border-radius: 8px;
}

/* Custom navigation buttons */
::ng-deep .cometchat-fullscreen-viewer__nav-button {
  background: rgba(255, 255, 255, 0.2);
  border-radius: 50%;
  width: 48px;
  height: 48px;
}

::ng-deep .cometchat-fullscreen-viewer__nav-button:hover {
  background: rgba(255, 255, 255, 0.3);
}

Accessibility

The Video 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 video thumbnails have ARIA labels
  • 1.3.1 Info and Relationships (Level A): Proper semantic structure
  • 2.1.1 Keyboard (Level A): All functionality available via keyboard
  • 2.4.7 Focus Visible (Level AA): Clear focus indicators in video player
  • 4.1.2 Name, Role, Value (Level A): All elements have accessible names

Keyboard Support

KeyActionContext
TabNavigate to video thumbnailsWhen thumbnails are focusable
EnterOpen video playerWhen thumbnail is focused
SpaceOpen video playerWhen thumbnail is focused
EscapeClose video playerIn video player

ARIA Attributes

The component automatically applies appropriate ARIA attributes:
AttributeElementValuePurpose
aria-labelVideo thumbnail"Video, [duration]"Provides text alternative
roleVideo player"dialog"Identifies the player as a dialog
aria-modalVideo player"true"Indicates modal behavior
aria-labelNavigation buttons"Next video", "Previous video"Describes button actions
aria-labelClose button"Close player"Describes close action
aria-labelOverflow indicator"+N more videos"Describes additional videos
aria-labelPlay button"Play video"Describes play action

Screen Reader Behavior

Screen readers announce the video bubble with:
  1. Single video: “Video, duration 2 minutes 5 seconds”
  2. Multiple videos: “Video 1 of 3, duration 1 minute 30 seconds”
  3. Overflow indicator: “+3 more videos”
  4. Video player: “Dialog, Video player, 2 of 5”
  5. Navigation: “Button, Next video” / “Button, Previous video”
  6. Play button: “Button, Play video”

Accessibility Best Practices

The component automatically handles all accessibility requirements. No additional ARIA attributes or keyboard handling is needed.
When handling videoClick events, ensure your custom actions maintain accessibility by managing focus appropriately.
All interactive elements (video thumbnails, navigation buttons, play button) are keyboard accessible and have visible focus indicators.

Best Practices

Always provide the complete CometChat.MediaMessage object to ensure all features (attachments, captions, metadata, duration) work correctly.
The component expects video attachments with valid URLs and thumbnails. 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 playerOpen and playerClose events to track analytics or perform custom actions when the video player is used.
The video player prevents body scroll while open. Avoid programmatically scrolling the page while the player is active.
The component uses lazy loading for video thumbnails. Thumbnails outside the viewport won’t load until they’re scrolled into view.
Video streams are only loaded when the player is opened. This prevents unnecessary bandwidth usage for videos that aren’t played.
  • CometChatImageBubble: Displays image messages with grid layouts and gallery
  • CometChatTextBubble: Used for rendering captions in video messages
  • CometChatMessageBubble: Uses Video Bubble as the content view for video messages
  • CometChatMessageList: Displays lists of messages including video bubbles
  • VideoPlayerViewer: Internal component for fullscreen video playback

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
    • VideoPlayerViewerComponent for fullscreen playback
  • Bundle Size: Minimal footprint (~14KB including video player)
  • BEM CSS: Follows Block Element Modifier naming convention
  • Accessibility: WCAG 2.1 Level AA compliant

Performance Considerations

Optimization Strategies

Change Detection:
  • Uses OnPush strategy to minimize unnecessary re-renders
  • Only updates when inputs change or events are emitted
Lazy Loading:
  • Video thumbnails use native loading="lazy" attribute
  • Thumbnails outside viewport don’t load until scrolled into view
  • Video streams only load when player is opened
  • Reduces initial page load time and bandwidth usage significantly
Layout Determination:
  • Layout type calculated once during message processing
  • Avoids repeated calculations during rendering
Video Player:
  • Only rendered when open (conditional rendering)
  • Video stops automatically on close to free resources
  • Body scroll prevention uses efficient CSS approach
  • Focus trap implemented with minimal DOM manipulation
Duration Formatting:
  • Duration formatted once during message processing
  • Cached for display in template

Best Practices for Performance

The component uses OnPush change detection. Ensure message objects are immutable for optimal performance.
Lazy loading is automatic. Video thumbnails will load as they enter the viewport during scrolling.
Avoid frequently changing the message input. Each change triggers re-processing of attachments and layout determination.
Video streams are only loaded when the player opens. This prevents unnecessary bandwidth usage for videos that aren’t played.
For troubleshooting tips, see the Troubleshooting Guide.