Skip to main content

Documentation Index

Fetch the complete documentation index at: https://cometchat-22654f5b-react-uikit-v7.mintlify.app/llms.txt

Use this file to discover all available pages before exploring further.

Overview

Custom plugins let you handle any message type with your own rendering logic. This guide walks through building a complete “Location” plugin that:
  1. Renders a map preview bubble
  2. Provides context menu options
  3. Shows a preview in the conversations list

Step 1: Define the Plugin

Create a file for your plugin that implements CometChatMessagePlugin:
src/plugins/LocationPlugin.tsx
import React from "react";
import type { CometChat } from "@cometchat/chat-sdk-javascript";
import type {
  CometChatMessagePlugin,
  CometChatMessagePluginContext,
  CometChatMessageOption,
} from "@cometchat/chat-uikit-react";

// Extract location data from the custom message
function getLocationData(message: CometChat.BaseMessage) {
  const customMessage = message as CometChat.CustomMessage;
  const data = customMessage.getCustomData() as {
    latitude?: number;
    longitude?: number;
    address?: string;
  } | undefined;
  return {
    latitude: data?.latitude ?? 0,
    longitude: data?.longitude ?? 0,
    address: data?.address ?? "",
  };
}

export const LocationPlugin: CometChatMessagePlugin = {
  id: "location",
  messageTypes: ["location"],
  messageCategories: ["custom"],

  renderBubble(message: CometChat.BaseMessage, context: CometChatMessagePluginContext) {
    const { latitude, longitude, address } = getLocationData(message);
    const mapUrl = `https://maps.googleapis.com/maps/api/staticmap?center=${latitude},${longitude}&zoom=15&size=300x200&markers=${latitude},${longitude}&key=YOUR_API_KEY`;

    return (
      <div className="location-bubble">
        <img
          src={mapUrl}
          alt={address || "Location"}
          style={{ borderRadius: 8, width: "100%", maxWidth: 300 }}
        />
        {address && (
          <p style={{ margin: "8px 0 0", fontSize: 13, color: "#666" }}>
            {address}
          </p>
        )}
        <a
          href={`https://maps.google.com/?q=${latitude},${longitude}`}
          target="_blank"
          rel="noopener noreferrer"
          style={{ fontSize: 12, color: "#6851FF" }}
        >
          Open in Maps
        </a>
      </div>
    );
  },

  getOptions(
    message: CometChat.BaseMessage,
    context: CometChatMessagePluginContext
  ): CometChatMessageOption[] {
    const options: CometChatMessageOption[] = [];

    // Copy coordinates
    options.push({
      id: "copy-location",
      title: "Copy Location",
      onClick: (msg) => {
        const { latitude, longitude } = getLocationData(msg);
        void navigator.clipboard.writeText(`${latitude}, ${longitude}`);
        context.showToast?.("Location copied to clipboard");
      },
    });

    // Delete (sender only)
    options.push({
      id: "delete",
      title: context.getLocalizedString?.("delete") ?? "Delete",
      senderOnly: true,
      onClick: (msg) => context.onDeleteMessage?.(msg),
    });

    return options;
  },

  getLastMessagePreview(
    message: CometChat.BaseMessage
  ): string {
    const { address } = getLocationData(message);
    return address ? `📍 ${address}` : "📍 Location";
  },
};

Step 2: Register the Plugin

Pass your plugin to CometChatProvider:
src/App.tsx
import { CometChatProvider } from "@cometchat/chat-uikit-react";
import { LocationPlugin } from "./plugins/LocationPlugin";

function App() {
  return (
    <CometChatProvider
      appId="YOUR_APP_ID"
      region="us"
      authKey="YOUR_AUTH_KEY"
      uid="cometchat-uid-1"
      plugins={[LocationPlugin]}
    >
      <MyChatApp />
    </CometChatProvider>
  );
}
Your plugin is appended after the default plugins. Since resolution is first-match, default plugins handle their types first, and your plugin handles "location" messages.

Step 3: Send a Location Message

Use the CometChat SDK to send a custom message with type "location":
import { CometChat } from "@cometchat/chat-sdk-javascript";
import { CometChatUIKit } from "@cometchat/chat-uikit-react";

async function sendLocation(receiverUid: string, lat: number, lng: number) {
  const message = new CometChat.CustomMessage(
    receiverUid,
    CometChat.RECEIVER_TYPE.USER,
    "location",
    { latitude: lat, longitude: lng, address: "123 Main St" }
  );

  await CometChatUIKit.sendCustomMessage(message);
}

Step 4: Style the Bubble

Add CSS for your bubble:
src/plugins/LocationPlugin.css
.location-bubble {
  padding: 4px;
  max-width: 300px;
}

.location-bubble img {
  display: block;
  border-radius: 8px;
}

Plugin Interface Quick Reference

interface CometChatMessagePlugin {
  id: string;                    // Unique identifier
  messageTypes: string[];        // SDK message types to handle
  messageCategories: string[];   // SDK message categories to handle

  // Required
  renderBubble(message, context): ReactNode;

  // Optional
  getOptions?(message, context): MessageOption[];
  getLastMessagePreview?(message, loggedInUser, t?): string;
  getTextFormatters?(): CometChatTextFormatter[];

  // View slot overrides (optional)
  renderLeadingView?(message, context): ReactNode;
  renderHeaderView?(message, context): ReactNode;
  renderFooterView?(message, context): ReactNode;
  renderBottomView?(message, context): ReactNode;
  renderStatusInfoView?(message, context): ReactNode;
  renderReplyView?(message, context): ReactNode;
  renderThreadView?(message, context): ReactNode;
}

Tips

  • Lazy-load heavy components — use React.lazy() + Suspense for bubble components that import large libraries
  • Use context.getLocalizedString — for any user-facing text in options or bubbles
  • Return [] from getOptions — for system messages that shouldn’t have a context menu
  • Keep getLastMessagePreview short — max ~100 characters, plain text only (no HTML)
  • Test with messageTypes array — a single plugin can handle multiple types (like the Call Action plugin handles both audio and video in the call category)