AI Agent Component Spec
AI Agent Component Spec
Report incorrect code
Copy
Ask AI
{
"component": "CometChatMessageBubble",
"package": "@cometchat/chat-uikit-react",
"import": "import { CometChatMessageBubble } from \"@cometchat/chat-uikit-react\";",
"cssImport": "import \"@cometchat/chat-uikit-react/css-variables.css\";",
"description": "Base component for rendering message bubbles with customizable content, header, footer, and styling.",
"cssRootClass": ".cometchat-message-bubble",
"relatedComponents": {
"CometChatTextBubble": "Text message content",
"CometChatImageBubble": "Image message content",
"CometChatVideoBubble": "Video message content",
"CometChatAudioBubble": "Audio message content",
"CometChatFileBubble": "File attachment content",
"CometChatDocumentBubble": "Document preview content"
},
"props": {
"data": {
"id": { "type": "string", "required": true },
"alignment": { "type": "MessageBubbleAlignment", "default": "left" }
},
"viewSlots": {
"leadingView": "JSX.Element",
"headerView": "JSX.Element",
"contentView": "JSX.Element",
"bottomView": "JSX.Element",
"footerView": "JSX.Element",
"statusInfoView": "JSX.Element",
"threadView": "JSX.Element"
}
}
}
Overview
This guide shows you how to customize message bubbles using CometChat’s bubble components. You’ll learn to create custom layouts for different message types and build entirely custom message presentations. Time estimate: 15 minutesDifficulty: Intermediate
Prerequisites
- React.js setup complete
- Messaging configured
- Understanding of Message Templates
Steps
Step 1: Understand Bubble Architecture
Message bubbles have several customizable slots:Report incorrect code
Copy
Ask AI
┌─────────────────────────────────────┐
│ leadingView │ headerView │
├─────────────┼───────────────────────┤
│ │ contentView │
│ ├───────────────────────┤
│ │ bottomView │
├─────────────┴───────────────────────┤
│ footerView │ statusInfoView│
├─────────────────────────────────────┤
│ threadView │
└─────────────────────────────────────┘
Step 2: Use Built-in Bubble Components
CometChat provides specialized bubble components for each message type:Report incorrect code
Copy
Ask AI
import {
CometChatTextBubble,
CometChatImageBubble,
CometChatVideoBubble,
CometChatAudioBubble,
CometChatFileBubble,
} from "@cometchat/chat-uikit-react";
import "@cometchat/chat-uikit-react/css-variables.css";
// Text message
function TextMessage({ text }: { text: string }) {
return <CometChatTextBubble text={text} />;
}
// Image message
function ImageMessage({ url }: { url: string }) {
return <CometChatImageBubble src={url} />;
}
// Video message
function VideoMessage({ url }: { url: string }) {
return <CometChatVideoBubble src={url} />;
}
// Audio message
function AudioMessage({ url }: { url: string }) {
return <CometChatAudioBubble src={url} />;
}
// File message
function FileMessage({ url, name }: { url: string; name: string }) {
return <CometChatFileBubble fileUrl={url} fileName={name} />;
}
Step 3: Create Custom Message Bubble
Build a complete custom bubble:Report incorrect code
Copy
Ask AI
import { CometChatMessageBubble, CometChatAvatar } from "@cometchat/chat-uikit-react";
import { CometChat } from "@cometchat/chat-sdk-javascript";
import "@cometchat/chat-uikit-react/css-variables.css";
interface CustomBubbleProps {
message: CometChat.TextMessage;
alignment: "left" | "right";
}
function CustomMessageBubble({ message, alignment }: CustomBubbleProps) {
const sender = message.getSender();
return (
<CometChatMessageBubble
id={String(message.getId())}
alignment={alignment}
leadingView={
alignment === "left" ? (
<CometChatAvatar
image={sender.getAvatar()}
name={sender.getName()}
/>
) : undefined
}
headerView={
<div className="bubble-header">
<span className="sender-name">{sender.getName()}</span>
<span className="timestamp">
{new Date(message.getSentAt() * 1000).toLocaleTimeString()}
</span>
</div>
}
contentView={
<div className="bubble-content">
{message.getText()}
</div>
}
footerView={
<div className="bubble-footer">
{message.getEditedAt() && <span>Edited</span>}
</div>
}
/>
);
}
Step 4: Integrate with Message Templates
Use custom bubbles in message templates:Report incorrect code
Copy
Ask AI
import {
CometChatMessageList,
CometChatMessageTemplate,
CometChatMessageBubble,
} from "@cometchat/chat-uikit-react";
import { CometChat } from "@cometchat/chat-sdk-javascript";
import "@cometchat/chat-uikit-react/css-variables.css";
function ChatWithCustomBubbles({ user }: { user: CometChat.User }) {
const customTextTemplate = new CometChatMessageTemplate({
type: "text",
category: "message",
contentView: (message: CometChat.BaseMessage) => {
const textMessage = message as CometChat.TextMessage;
return (
<div className="custom-text-content">
<p>{textMessage.getText()}</p>
<span className="word-count">
{textMessage.getText().split(" ").length} words
</span>
</div>
);
},
});
return (
<CometChatMessageList
user={user}
templates={[customTextTemplate]}
/>
);
}
Complete Example
Full implementation with multiple custom bubble types:Report incorrect code
Copy
Ask AI
import { useState, useEffect } from "react";
import {
CometChatMessageList,
CometChatMessageComposer,
CometChatMessageTemplate,
CometChatTextBubble,
CometChatImageBubble,
CometChatAvatar,
} from "@cometchat/chat-uikit-react";
import { CometChat } from "@cometchat/chat-sdk-javascript";
import "@cometchat/chat-uikit-react/css-variables.css";
function ChatWithCustomBubbles() {
const [user, setUser] = useState<CometChat.User | null>(null);
useEffect(() => {
CometChat.getUser("USER_ID").then(setUser);
}, []);
// Custom text bubble with reactions preview
const customTextTemplate = new CometChatMessageTemplate({
type: "text",
category: "message",
contentView: (message: CometChat.BaseMessage) => {
const textMessage = message as CometChat.TextMessage;
return (
<div className="enhanced-text-bubble">
<CometChatTextBubble text={textMessage.getText()} />
{textMessage.getReactions()?.length > 0 && (
<div className="reactions-preview">
{textMessage.getReactions().slice(0, 3).map((r, i) => (
<span key={i}>{r.getReaction()}</span>
))}
</div>
)}
</div>
);
},
});
// Custom image bubble with download button
const customImageTemplate = new CometChatMessageTemplate({
type: "image",
category: "message",
contentView: (message: CometChat.BaseMessage) => {
const mediaMessage = message as CometChat.MediaMessage;
const url = mediaMessage.getAttachment()?.getUrl() || "";
return (
<div className="enhanced-image-bubble">
<CometChatImageBubble src={url} />
<button
className="download-button"
onClick={() => window.open(url, "_blank")}
>
⬇️ Download
</button>
</div>
);
},
});
if (!user) return <div>Loading...</div>;
return (
<div style={{ display: "flex", flexDirection: "column", height: "100vh" }}>
<CometChatMessageList
user={user}
templates={[customTextTemplate, customImageTemplate]}
/>
<CometChatMessageComposer user={user} />
</div>
);
}
export default ChatWithCustomBubbles;
Advanced Configuration
Advanced Configuration
Custom Bubble for Custom Messages
Handle custom message types:Report incorrect code
Copy
Ask AI
import { CometChatMessageTemplate } from "@cometchat/chat-uikit-react";
import { CometChat } from "@cometchat/chat-sdk-javascript";
// Custom location message bubble
const locationTemplate = new CometChatMessageTemplate({
type: "location",
category: "custom",
contentView: (message: CometChat.BaseMessage) => {
const customMessage = message as CometChat.CustomMessage;
const data = customMessage.getData()?.customData;
return (
<div className="location-bubble">
<div className="location-map">
<img
src={`https://maps.googleapis.com/maps/api/staticmap?center=${data.lat},${data.lng}&zoom=15&size=200x150&key=YOUR_API_KEY`}
alt="Location"
/>
</div>
<div className="location-info">
<strong>{data.name || "Shared Location"}</strong>
<a
href={`https://maps.google.com/?q=${data.lat},${data.lng}`}
target="_blank"
rel="noopener noreferrer"
>
Open in Maps
</a>
</div>
</div>
);
},
});
Bubble with Actions
Add interactive actions to bubbles:Report incorrect code
Copy
Ask AI
import { CometChatMessageTemplate } from "@cometchat/chat-uikit-react";
import { CometChat } from "@cometchat/chat-sdk-javascript";
const interactiveTemplate = new CometChatMessageTemplate({
type: "text",
category: "message",
contentView: (message: CometChat.BaseMessage) => {
const textMessage = message as CometChat.TextMessage;
return (
<div className="interactive-bubble">
<p>{textMessage.getText()}</p>
<div className="bubble-actions">
<button onClick={() => handleReply(message)}>Reply</button>
<button onClick={() => handleForward(message)}>Forward</button>
<button onClick={() => handleCopy(textMessage.getText())}>Copy</button>
</div>
</div>
);
},
});
function handleReply(message: CometChat.BaseMessage) {
console.log("Reply to:", message.getId());
}
function handleForward(message: CometChat.BaseMessage) {
console.log("Forward:", message.getId());
}
function handleCopy(text: string) {
navigator.clipboard.writeText(text);
}
Animated Bubbles
Add animations to message bubbles:Report incorrect code
Copy
Ask AI
import { CometChatMessageTemplate } from "@cometchat/chat-uikit-react";
import { CometChat } from "@cometchat/chat-sdk-javascript";
const animatedTemplate = new CometChatMessageTemplate({
type: "text",
category: "message",
contentView: (message: CometChat.BaseMessage) => {
const textMessage = message as CometChat.TextMessage;
return (
<div
className="animated-bubble"
style={{
animation: "slideIn 0.3s ease-out",
}}
>
{textMessage.getText()}
</div>
);
},
});
Styling
Customize bubble appearance:Report incorrect code
Copy
Ask AI
/* Base bubble styles */
.cometchat-message-bubble {
margin: 8px 16px;
max-width: 70%;
}
.cometchat-message-bubble--left {
margin-right: auto;
}
.cometchat-message-bubble--right {
margin-left: auto;
}
/* Content area */
.cometchat-message-bubble__content {
padding: 12px 16px;
border-radius: 16px;
background: #f5f5f5;
}
.cometchat-message-bubble--right .cometchat-message-bubble__content {
background: #6852d6;
color: #ffffff;
}
/* Header */
.bubble-header {
display: flex;
justify-content: space-between;
margin-bottom: 4px;
font-size: 12px;
}
.sender-name {
font-weight: 600;
}
.timestamp {
color: #999;
}
/* Custom enhancements */
.enhanced-text-bubble {
position: relative;
}
.reactions-preview {
position: absolute;
bottom: -8px;
right: 8px;
background: #ffffff;
border-radius: 12px;
padding: 2px 6px;
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
}
.enhanced-image-bubble {
position: relative;
}
.download-button {
position: absolute;
bottom: 8px;
right: 8px;
padding: 4px 8px;
border-radius: 4px;
background: rgba(0, 0, 0, 0.6);
color: #ffffff;
border: none;
cursor: pointer;
}
/* Animation */
@keyframes slideIn {
from {
opacity: 0;
transform: translateY(10px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
Common Issues
When customizing bubbles, ensure you handle all message states including loading, error, and deleted messages.
| Issue | Solution |
|---|---|
| Bubble not rendering | Check message type matches template type |
| Styling conflicts | Use specific CSS selectors with component classes |
| Missing content | Ensure contentView returns valid JSX |
| Performance issues | Avoid heavy computations in render functions |