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

Overview

The Image Bubble component renders image messages while maintaining visual consistency with the design system and ensuring full accessibility:
  • Message Object Processing: Extracts attachments and metadata from CometChat.MediaMessage objects
  • Single Image Display: Full-size image rendering with click-to-expand
  • Fullscreen Gallery: Modal viewer with keyboard controls
  • Caption Support: Renders captions using TextMessageBubbleComponent
  • Lazy Loading: Performance optimization for image loading
  • Dual Styling: Supports sender (outgoing) and receiver (incoming) visual variants
  • Accessibility: Full keyboard navigation and screen reader support
Live Preview — Default image bubble preview. Open in Storybook ↗

Basic Usage

Simple Image Message

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

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

Incoming vs Outgoing Messages

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

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

    <!-- Outgoing message (right-aligned) -->
    <cometchat-image-bubble
      [message]="outgoingMessage"
      [alignment]="MessageBubbleAlignment.RIGHT"
    ></cometchat-image-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 { CometChatImageBubbleComponent, MediaAttachment } from '@cometchat/chat-uikit-angular';

@Component({
  selector: 'app-interactive-message',
  standalone: true,
  imports: [CometChatImageBubbleComponent],
  template: `
    <cometchat-image-bubble
      [message]="imageMessage"
      (imageClick)="onImageClick($event)"
      (viewerOpen)="onViewerOpen()"
      (viewerClose)="onViewerClose()"
    ></cometchat-image-bubble>
  `
})
export class InteractiveMessageComponent {
  imageMessage!: CometChat.MediaMessage;

  onImageClick(event: { attachment: MediaAttachment; index: number }): void {
    console.log('Image clicked:', event.attachment.url, 'at index:', event.index);
    // Handle image click - gallery viewer opens automatically
  }

  onViewerOpen(): void {
    console.log('Gallery viewer opened');
    // Track analytics or perform other actions
  }

  onViewerClose(): void {
    console.log('Gallery viewer closed');
    // Track analytics or perform other actions
  }
}

Properties

PropertyTypeDefaultDescription
messageCometChat.MediaMessagerequiredThe CometChat.MediaMessage object to render. Contains image 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
imageClick{ attachment: MediaAttachment; index: number }Emitted when an image is clicked. Contains the clicked attachment object and its index in the attachments array
viewerOpenvoidEmitted when the fullscreen gallery viewer is opened
viewerClosevoidEmitted when the fullscreen gallery viewer is closed

Advanced Usage

Single Image Message

The component displays single image messages in full-size layout:
import { Component } from '@angular/core';
import { CometChat } from '@cometchat/chat-sdk-javascript';
import { CometChatImageBubbleComponent } from '@cometchat/chat-uikit-angular';

@Component({
  selector: 'app-single-image',
  standalone: true,
  imports: [CometChatImageBubbleComponent],
  template: `
    <cometchat-image-bubble
      [message]="singleImageMessage"
    ></cometchat-image-bubble>
  `
})
export class SingleImageComponent {
  singleImageMessage!: CometChat.MediaMessage;
}
Single Image Features:
  • Full-width display with aspect ratio preservation
  • Lazy loading for performance
  • Click to open fullscreen gallery viewer
  • Alt text for accessibility

Images with Captions

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

@Component({
  selector: 'app-captioned-image',
  standalone: true,
  imports: [CometChatImageBubbleComponent],
  template: `
    <cometchat-image-bubble
      [message]="captionedImageMessage"
    ></cometchat-image-bubble>
  `
})
export class CaptionedImageComponent {
  captionedImageMessage!: CometChat.MediaMessage;
  
  // Message with caption in metadata:
  // message.getText() returns "Beautiful sunset at the beach"
  // OR
  // message.getData()?.text returns "Beautiful sunset at the beach"
}
Caption Features:
  • Displays below the image(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 includes an integrated fullscreen gallery viewer with navigation:
import { Component } from '@angular/core';
import { CometChat } from '@cometchat/chat-sdk-javascript';
import { CometChatImageBubbleComponent } from '@cometchat/chat-uikit-angular';

@Component({
  selector: 'app-gallery-demo',
  standalone: true,
  imports: [CometChatImageBubbleComponent],
  template: `
    <cometchat-image-bubble
      [message]="imageMessage"
      (viewerOpen)="onGalleryOpen()"
      (viewerClose)="onGalleryClose()"
    ></cometchat-image-bubble>
  `
})
export class GalleryDemoComponent {
  imageMessage!: CometChat.MediaMessage;

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

  onGalleryClose(): void {
    console.log('Gallery closed - track analytics');
    // Body scroll is automatically restored
  }
}
Gallery Viewer Features:
  • Fullscreen modal overlay
  • Current image displayed at full size
  • Navigation controls (previous/next buttons)
  • Image counter (e.g., “3 of 10”)
  • Close button
  • Keyboard navigation:
    • Right Arrow - Next image
    • Left Arrow - Previous image
    • Escape - Close viewer
  • Click backdrop to close
  • Focus trap for accessibility
  • Body scroll prevention while open

Customization

Styling with CSS Variables

The Image Bubble component uses CSS variables exclusively for easy customization:
/* Custom image bubble styling */
cometchat-image-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;

  /* Overflow overlay */
  --cometchat-text-color-white: #FFFFFF;
  --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-2Image border radius8px
--cometchat-radius-3Bubble border radius12px
--cometchat-background-color-02Incoming bubble background#F5F5F5
--cometchat-primary-button-backgroundOutgoing bubble background#6852D6
--cometchat-border-color-lightBorder color#E0E0E0
--cometchat-text-color-whiteOverflow text color#FFFFFF
--cometchat-font-heading2-boldOverflow text font600 20px Roboto

Custom Color Schemes

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

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

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

Custom Grid Spacing

/* Tighter grid spacing */
.compact-images cometchat-image-bubble {
  --cometchat-spacing-1: 2px;
}

/* Wider grid spacing */
.spacious-images cometchat-image-bubble {
  --cometchat-spacing-1: 8px;
}

Custom Overflow Indicator Styling

/* Custom overflow overlay styling */
::ng-deep .cometchat-image-bubble__overflow-overlay {
  background: linear-gradient(135deg, rgba(104, 82, 214, 0.9), rgba(104, 82, 214, 0.7));
}

::ng-deep .cometchat-image-bubble__overflow-text {
  font-size: 24px;
  font-weight: 700;
  text-shadow: 0 2px 4px rgba(0, 0, 0, 0.3);
}
/* Custom fullscreen viewer backdrop */
::ng-deep .cometchat-fullscreen-viewer__backdrop {
  background: rgba(0, 0, 0, 0.95);
}

/* 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);
}

/* Custom close button */
::ng-deep .cometchat-fullscreen-viewer__close-button {
  background: rgba(255, 255, 255, 0.2);
  border-radius: 50%;
  padding: 12px;
}

Accessibility

The Image 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 images have alt text
  • 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 gallery viewer
  • 4.1.2 Name, Role, Value (Level A): All elements have accessible names

Keyboard Support

KeyActionContext
TabNavigate to imagesWhen images are focusable
EnterOpen gallery viewerWhen image is focused
SpaceOpen gallery viewerWhen image is focused
Right ArrowNext imageIn gallery viewer
Left ArrowPrevious imageIn gallery viewer
EscapeClose gallery viewerIn gallery viewer

ARIA Attributes

The component automatically applies appropriate ARIA attributes:
AttributeElementValuePurpose
altImage elementsDescriptive textProvides text alternative for images
roleGallery viewer"dialog"Identifies the viewer as a dialog
aria-modalGallery viewer"true"Indicates modal behavior
aria-labelNavigation buttons"Next image", "Previous image"Describes button actions
aria-labelClose button"Close gallery"Describes close action
aria-labelOverflow indicator"+N more images"Describes additional images

Screen Reader Behavior

Screen readers announce the image bubble with:
  1. Single image: “Image, [alt text]”
  2. Multiple images: “Image 1 of 3, [alt text]”
  3. Overflow indicator: “+3 more images”
  4. Gallery viewer: “Dialog, Image gallery, 2 of 5”
  5. Navigation: “Button, Next image” / “Button, Previous image”

Accessibility Best Practices

The component automatically handles all accessibility requirements. No additional ARIA attributes or keyboard handling is needed.
When handling imageClick events, ensure your custom actions maintain accessibility by managing focus appropriately.
All interactive elements (images, navigation buttons) 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 image 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 viewerOpen and viewerClose events to track analytics or perform custom actions when the gallery is used.
The gallery viewer prevents body scroll while open. Avoid programmatically scrolling the page while the viewer is active.
The component uses lazy loading for images. Images outside the viewport won’t load until they’re scrolled into view.
  • CometChatVideoBubble: Displays video messages with thumbnails and player
  • CometChatTextBubble: Used for rendering captions in image messages
  • CometChatMessageBubble: Uses Image Bubble as the content view for image messages
  • CometChatMessageList: Displays lists of messages including image bubbles
  • ImageGalleryViewer: Internal component for fullscreen image viewing

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
    • ImageGalleryViewerComponent for fullscreen viewing
  • Bundle Size: Minimal footprint (~12KB including gallery viewer)
  • 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:
  • Images use native loading="lazy" attribute
  • Images outside viewport don’t load until scrolled into view
  • Reduces initial page load time and bandwidth usage
Layout Determination:
  • Layout type calculated once during message processing
  • Avoids repeated calculations during rendering
Gallery Viewer:
  • Only rendered when open (conditional rendering)
  • Body scroll prevention uses efficient CSS approach
  • Focus trap implemented with minimal DOM manipulation

Best Practices for Performance

The component uses OnPush change detection. Ensure message objects are immutable for optimal performance.
Lazy loading is automatic. Images 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.
For troubleshooting tips, see the Troubleshooting Guide.