Skip to main content
{
  "component": "CometChatMessageTemplate",
  "kind": "model-class",
  "package": "@cometchat/chat-uikit-react",
  "import": "import { CometChatMessageTemplate } from \"@cometchat/chat-uikit-react\";",
  "description": "Data structure defining how message bubbles render in CometChatMessageList. Each template maps a type+category pair to view functions.",
  "usage": "Pass an array of CometChatMessageTemplate instances to CometChatMessageList via the templates prop.",
  "properties": {
    "type": { "type": "string", "required": true, "description": "CometChat message type" },
    "category": { "type": "string", "default": "\"\"", "description": "CometChat message category" },
    "headerView": { "type": "function | null", "default": "null", "description": "Custom header view function" },
    "contentView": { "type": "function | null", "default": "null", "description": "Custom content view function" },
    "footerView": { "type": "function | null", "default": "null", "description": "Custom footer view function" },
    "bottomView": { "type": "function | null", "default": "null", "description": "Custom bottom view function" },
    "bubbleView": { "type": "function | null", "default": "null", "description": "Replaces entire bubble" },
    "statusInfoView": { "type": "function | null", "default": "null", "description": "Custom status info view function" },
    "replyView": { "type": "function | null", "default": "null", "description": "Custom reply preview function" },
    "options": { "type": "function", "description": "Returns action sheet items for long-press" }
  },
  "relatedComponents": ["CometChatMessageList"],
  "cssRootClass": null,
  "events": null
}

What It Is

CometChatMessageTemplate is a model class, not a rendered component. Each instance maps a message type + category pair to a set of view functions that control how that message renders inside CometChatMessageList. Pass an array of templates to the templates prop on CometChatMessageList.
import { useState, useEffect } from "react";
import {
  CometChatMessageList,
  CometChatMessageTemplate,
  CometChatUIKit,
  CometChatUIKitConstants,
} from "@cometchat/chat-uikit-react";
import { CometChat } from "@cometchat/chat-sdk-javascript";

function CustomTemplateDemo() {
  const [chatGroup, setChatGroup] = useState<CometChat.Group>();
  const [templates, setTemplates] = useState<CometChatMessageTemplate[]>([]);

  useEffect(() => {
    CometChat.getGroup("guid").then((group) => setChatGroup(group));

    const allTemplates = CometChatUIKit.getDataSource().getAllMessageTemplates();
    const modified = allTemplates.map((t) => {
      if (
        t.type === CometChatUIKitConstants.MessageTypes.text &&
        t.category === CometChatUIKitConstants.MessageCategory.message
      ) {
        t.headerView = (message: CometChat.BaseMessage) => (
          <>{message.getSender().getName()} • 🗓️ In meeting</>
        );
      }
      return t;
    });
    setTemplates(modified);
  }, []);

  if (!chatGroup) return null;

  return <CometChatMessageList group={chatGroup} templates={templates} />;
}

Template Structure

A message bubble is composed of these view slots, each overridable per template:
ViewDefault renderingSignature
headerViewSender name(message: CometChat.BaseMessage, alignment: MessageBubbleAlignment, textFormatters?: CometChatTextFormatter[]) => JSX.Element | null
contentViewText / image / video / audio / file bubble(message: CometChat.BaseMessage, alignment: MessageBubbleAlignment, textFormatters?: CometChatTextFormatter[]) => JSX.Element | null
footerViewReactions(message: CometChat.BaseMessage, alignment: MessageBubbleAlignment) => JSX.Element | null
bottomViewLink previews, “load more”(message: CometChat.BaseMessage, alignment: MessageBubbleAlignment) => JSX.Element | null
statusInfoViewReceipt + timestamp(message: CometChat.BaseMessage, alignment: MessageBubbleAlignment, hideReceipts?: boolean, messageSentAtDateTimeFormat?: CalendarObject, showError?: boolean) => JSX.Element | null
replyViewReply preview(message: CometChat.BaseMessage, alignment?: MessageBubbleAlignment, onReplyViewClicked?: (msg: CometChat.BaseMessage) => void, textFormatters?: CometChatTextFormatter[]) => JSX.Element | null
bubbleViewEntire bubble (overrides all above)(message: CometChat.BaseMessage, alignment: MessageBubbleAlignment) => JSX.Element | null
optionsLong-press action sheet(loggedInUser: CometChat.User, message: CometChat.BaseMessage, group?: CometChat.Group) => CometChatMessageOption[]

Fetching Existing Templates

Retrieve the built-in templates and modify specific ones:
import {
  CometChatUIKit,
  CometChatUIKitConstants,
  CometChatMessageTemplate,
} from "@cometchat/chat-uikit-react";

const allTemplates: CometChatMessageTemplate[] =
  CometChatUIKit.getDataSource().getAllMessageTemplates();

for (let i = 0; i < allTemplates.length; i++) {
  if (allTemplates[i].type === CometChatUIKitConstants.MessageTypes.text) {
    // customize allTemplates[i]
  }
}

Common Patterns

Custom header with status badge

import { useState, useEffect } from "react";
import {
  CometChatMessageList,
  CometChatUIKit,
  CometChatUIKitConstants,
  CometChatMessageTemplate,
} from "@cometchat/chat-uikit-react";
import { CometChat } from "@cometchat/chat-sdk-javascript";

function HeaderViewDemo() {
  const [chatGroup, setChatGroup] = useState<CometChat.Group>();
  const [templates, setTemplates] = useState<CometChatMessageTemplate[]>([]);

  useEffect(() => {
    CometChat.getGroup("guid").then((group) => setChatGroup(group));

    const definedTemplates = CometChatUIKit.getDataSource().getAllMessageTemplates();
    const modified = definedTemplates.map((t) => {
      if (
        t.type === CometChatUIKitConstants.MessageTypes.text &&
        t.category === CometChatUIKitConstants.MessageCategory.message
      ) {
        t.headerView = (message: CometChat.BaseMessage) => (
          <>{message.getSender().getName()} • 🗓️ In meeting</>
        );
      }
      return t;
    });
    setTemplates(modified);
  }, []);

  if (!chatGroup) return null;

  return <CometChatMessageList group={chatGroup} templates={templates} />;
}

Custom content view for a custom message type

import { useState, useEffect } from "react";
import {
  CometChatMessageList,
  CometChatUIKit,
  CometChatUIKitConstants,
  CometChatMessageTemplate,
} from "@cometchat/chat-uikit-react";
import { CometChat } from "@cometchat/chat-sdk-javascript";

function ContentViewDemo() {
  const [chatGroup, setChatGroup] = useState<CometChat.Group>();
  const [templates, setTemplates] = useState<CometChatMessageTemplate[]>([]);

  useEffect(() => {
    CometChat.getGroup("guid").then((group) => setChatGroup(group));

    const definedTemplates = CometChatUIKit.getDataSource().getAllMessageTemplates();
    const CUSTOM_MESSAGE_TYPE = "customType";
    const customTemplate = new CometChatMessageTemplate({
      type: CUSTOM_MESSAGE_TYPE,
      category: CometChatUIKitConstants.MessageCategory.custom,
      contentView: (message: CometChat.BaseMessage) => (
        <div className="content-view">
          <div className="content-view__body">
            <div className="content-view__body-title">Blazer Casual</div>
            <div className="content-view__body-description">
              Men's Tailored Regular Fit Blazer
            </div>
            <div className="content-view__body-price">
              $37.99 <span className="content-view__body-price-old">$74.00</span>
            </div>
          </div>
          <div className="content-footer">Buy now</div>
        </div>
      ),
    });
    definedTemplates.push(customTemplate);
    setTemplates(definedTemplates);
  }, []);

  const getMessageRequestBuilder = () => {
    const CUSTOM_MESSAGE_TYPE = "customType";
    const categories = CometChatUIKit.getDataSource().getAllMessageCategories();
    categories.push(CometChatUIKitConstants.MessageCategory.custom);
    const types = CometChatUIKit.getDataSource().getAllMessageTypes();
    types.push(CUSTOM_MESSAGE_TYPE);
    return new CometChat.MessagesRequestBuilder()
      .setCategories(categories)
      .setTypes(types)
      .hideReplies(true)
      .setLimit(30);
  };

  if (!chatGroup) return null;

  return (
    <CometChatMessageList
      group={chatGroup}
      templates={templates}
      messagesRequestBuilder={getMessageRequestBuilder()}
    />
  );
}

Custom bottom view with warning

import { useState, useEffect } from "react";
import {
  CometChatMessageList,
  CometChatUIKit,
  CometChatUIKitConstants,
  CometChatMessageTemplate,
} from "@cometchat/chat-uikit-react";
import { CometChat } from "@cometchat/chat-sdk-javascript";

function BottomViewDemo() {
  const [chatGroup, setChatGroup] = useState<CometChat.Group>();
  const [templates, setTemplates] = useState<CometChatMessageTemplate[]>([]);

  useEffect(() => {
    CometChat.getGroup("guid").then((group) => setChatGroup(group));

    const definedTemplates = CometChatUIKit.getDataSource().getAllMessageTemplates();
    const modified = definedTemplates.map((t) => {
      if (
        t.type === CometChatUIKitConstants.MessageTypes.text &&
        t.category === CometChatUIKitConstants.MessageCategory.message
      ) {
        t.bottomView = (message: CometChat.BaseMessage) => (
          <div className="bottom-view">
            <span className="error-icon"> </span> According to guidelines you cannot share contact
          </div>
        );
      }
      return t;
    });
    setTemplates(modified);
  }, []);

  if (!chatGroup) return null;

  return <CometChatMessageList group={chatGroup} templates={templates} />;
}

Replace entire bubble

import { useState, useEffect } from "react";
import {
  CometChatMessageList,
  CometChatUIKit,
  CometChatUIKitConstants,
  CometChatMessageTemplate,
  MessageBubbleAlignment,
  CometChatUIKitLoginListener,
  MessageReceiptUtils,
  Receipts,
  isMessageSentByMe,
} from "@cometchat/chat-uikit-react";
import { CometChat } from "@cometchat/chat-sdk-javascript";

function BubbleViewDemo() {
  const [chatGroup, setChatGroup] = useState<CometChat.Group>();
  const [templates, setTemplates] = useState<CometChatMessageTemplate[]>([]);

  useEffect(() => {
    CometChat.getGroup("guid").then((group) => setChatGroup(group));

    const definedTemplates = CometChatUIKit.getDataSource().getAllMessageTemplates();
    const modified = definedTemplates.map((t) => {
      if (
        t.type === CometChatUIKitConstants.MessageTypes.text &&
        t.category === CometChatUIKitConstants.MessageCategory.message
      ) {
        t.bubbleView = (
          message: CometChat.BaseMessage,
          alignment: MessageBubbleAlignment
        ) => {
          const isSentByMe = isMessageSentByMe(
            message,
            CometChatUIKitLoginListener.getLoggedInUser()!
          );
          let textMessage = "";
          if (message instanceof CometChat.TextMessage) {
            textMessage = message.getText();
          }
          return (
            <div className={`bubble-view ${isSentByMe ? "bubble-view__outgoing" : "bubble-view__incoming"}`}>
              <div className="bubble-view__content">
                <div className="bubble-view__content__text">{textMessage}</div>
              </div>
            </div>
          );
        };
      }
      return t;
    });
    setTemplates(modified);
  }, []);

  if (!chatGroup) return null;

  return <CometChatMessageList group={chatGroup} templates={templates} />;
}

Custom action sheet options

import { useState, useEffect } from "react";
import {
  CometChatMessageList,
  CometChatUIKit,
  CometChatUIKitConstants,
  CometChatMessageTemplate,
  CometChatActionsIcon,
} from "@cometchat/chat-uikit-react";
import { CometChat } from "@cometchat/chat-sdk-javascript";

function OptionsDemo() {
  const [chatGroup, setChatGroup] = useState<CometChat.Group>();
  const [templates, setTemplates] = useState<CometChatMessageTemplate[]>([]);

  useEffect(() => {
    CometChat.getGroup("guid").then((group) => setChatGroup(group));

    const definedTemplates = CometChatUIKit.getDataSource().getAllMessageTemplates();
    const modified = definedTemplates.map((t) => {
      if (
        t.type === CometChatUIKitConstants.MessageTypes.text &&
        t.category === CometChatUIKitConstants.MessageCategory.message
      ) {
        t.options = (
          loggedInUser: CometChat.User,
          message: CometChat.BaseMessage,
          group?: CometChat.Group
        ) => {
          const defaultOptions: any =
            CometChatUIKit.getDataSource().getMessageOptions(loggedInUser, message, group);
          const myView: any = new CometChatActionsIcon({
            id: "refresh",
            title: "Refresh",
            iconURL: "",
            onClick: () => { /* custom logic */ },
          });
          defaultOptions.splice(1, 0, myView);
          return defaultOptions;
        };
      }
      return t;
    });
    setTemplates(modified);
  }, []);

  if (!chatGroup) return null;

  return <CometChatMessageList group={chatGroup} templates={templates} />;
}

New template for a custom message type

import { useState, useEffect } from "react";
import {
  CometChatMessageList,
  CometChatUIKit,
  CometChatUIKitConstants,
  CometChatMessageTemplate,
} from "@cometchat/chat-uikit-react";
import { CometChat } from "@cometchat/chat-sdk-javascript";

function NewTemplateDemo() {
  const [chatGroup, setChatGroup] = useState<CometChat.Group>();
  const [templates, setTemplates] = useState<CometChatMessageTemplate[]>([]);

  useEffect(() => {
    CometChat.getGroup("guid").then((group) => setChatGroup(group));

    const definedTemplates = CometChatUIKit.getDataSource().getAllMessageTemplates();
    const CUSTOM_MESSAGE_TYPE = "customType";
    const customTemplate = new CometChatMessageTemplate({
      type: CUSTOM_MESSAGE_TYPE,
      category: CometChatUIKitConstants.MessageCategory.custom,
      contentView: (message: CometChat.BaseMessage) => (
        <div style={{ padding: 8 }}>Custom: {JSON.stringify(message.getData())}</div>
      ),
    });
    definedTemplates.push(customTemplate);
    setTemplates(definedTemplates);
  }, []);

  const getMessageRequestBuilder = () => {
    const CUSTOM_MESSAGE_TYPE = "customType";
    const categories = CometChatUIKit.getDataSource().getAllMessageCategories();
    categories.push(CometChatUIKitConstants.MessageCategory.custom);
    const types = CometChatUIKit.getDataSource().getAllMessageTypes();
    types.push(CUSTOM_MESSAGE_TYPE);
    return new CometChat.MessagesRequestBuilder()
      .setCategories(categories)
      .setTypes(types)
      .hideReplies(true)
      .setLimit(30);
  };

  if (!chatGroup) return null;

  return (
    <CometChatMessageList
      group={chatGroup}
      templates={templates}
      messagesRequestBuilder={getMessageRequestBuilder()}
    />
  );
}

Styling

CometChatMessageTemplate renders inside .cometchat-message-bubble. Style individual bubble sections using CSS:
.cometchat .cometchat-message-bubble__body {
  /* content area overrides */
}

.cometchat .cometchat-message-bubble__body-footer-view {
  /* footer area overrides */
}

.cometchat .cometchat-message-bubble__body-header-view {
  /* header area overrides */
}

Accessibility

Message templates render inside CometChatMessageList, which handles keyboard navigation and focus management. Custom views returned from template functions inherit the bubble’s focus and ARIA context. Ensure custom content includes appropriate aria-label attributes when visual-only indicators are used.

Properties

bubbleView

KeyValue
Type((message: CometChat.BaseMessage, alignment: MessageBubbleAlignment) => Element | JSX.Element | null) | null
Defaultnull
Replaces the entire message bubble. When set, headerView, contentView, footerView, bottomView, statusInfoView, and replyView are ignored for that template.

bottomView

KeyValue
Type((message: CometChat.BaseMessage, alignment: MessageBubbleAlignment) => Element | JSX.Element | null) | null
Defaultnull
Custom bottom section below the content area. Default renders link previews or “load more” for long messages.

category

KeyValue
Typestring
Default""
Maps the template to a CometChat message category (e.g., CometChatUIKitConstants.MessageCategory.message, CometChatUIKitConstants.MessageCategory.custom).

contentView

KeyValue
Type((message: CometChat.BaseMessage, alignment: MessageBubbleAlignment, textFormatters?: CometChatTextFormatter[]) => Element | JSX.Element | null) | null
Defaultnull
Custom content area. Default renders text, image, video, audio, or file bubble based on message type.

footerView

KeyValue
Type((message: CometChat.BaseMessage, alignment: MessageBubbleAlignment) => Element | JSX.Element | null) | null
Defaultnull
Custom footer below the content area. Default renders reactions.

headerView

KeyValue
Type((message: CometChat.BaseMessage, alignment: MessageBubbleAlignment) => Element | JSX.Element | null) | null
Defaultnull
Custom header above the content area. Default renders sender name.

options

KeyValue
Type(loggedInUser: CometChat.User, message: CometChat.BaseMessage, group?: CometChat.Group) => CometChatMessageOption[]
DefaultSDK default options
Returns the list of action sheet items for long-press on a message bubble.

replyView

KeyValue
Type((message: CometChat.BaseMessage, alignment?: MessageBubbleAlignment, onReplyViewClicked?: (msg: CometChat.BaseMessage) => void, textFormatters?: CometChatTextFormatter[]) => Element | JSX.Element | null) | null
Defaultnull
Custom reply preview above the content area.

statusInfoView

KeyValue
Type((message: CometChat.BaseMessage, alignment: MessageBubbleAlignment, hideReceipts?: boolean, messageSentAtDateTimeFormat?: CalendarObject, showError?: boolean) => Element | JSX.Element | null) | null
Defaultnull
Custom status info area. Default renders receipt icon and timestamp.

type

KeyValue
Typestring
Default— (required)
Maps the template to a CometChat message type (e.g., CometChatUIKitConstants.MessageTypes.text, CometChatUIKitConstants.MessageTypes.image).