Skip to main content
{
  "package": "@cometchat/chat-uikit-react",
  "keyClass": "CometChatUrlsFormatter",
  "extends": "CometChatTextFormatter",
  "purpose": "Auto-detect URLs in text messages and convert them to clickable links"
}

Overview

CometChatUrlsFormatter detects URLs in text messages and renders them as clickable links. You can customize the styling and add click tracking. Time estimate: 10 minutes
Difficulty: Intermediate

Prerequisites

URL formatter showing clickable links

Steps

Step 1: Create the formatter class

Extend CometChatTextFormatter with URL regex patterns:
import { CometChatTextFormatter } from "@cometchat/chat-uikit-react";

class CometChatUrlsFormatter extends CometChatTextFormatter {
  constructor() {
    super();
    // Set regex patterns for URL detection
    this.setRegexPatterns([
      /(https?:\/\/[^\s]+)/g,
      /(www\.[^\s]+)/g,
    ]);
  }

  onRegexMatch(inputText: string): string {
    return this.formatUrls(inputText);
  }

  private formatUrls(text: string): string {
    // Replace URLs with clickable links
    return text.replace(
      /(https?:\/\/[^\s]+)/g,
      '<a href="$1" class="clickable-url" target="_blank" rel="noopener noreferrer">$1</a>'
    );
  }

  registerEventListeners(element: HTMLElement, classList: DOMTokenList): HTMLElement {
    if (classList.contains("clickable-url")) {
      element.addEventListener("click", this.onUrlClick);
    }
    return element;
  }

  private onUrlClick = (event: Event) => {
    const target = event.target as HTMLAnchorElement;
    const url = target.href;
    console.log("URL clicked:", url);
    // Add tracking logic here
  };

  getFormattedText(text: string): string {
    return this.formatUrls(text);
  }
}

export default CometChatUrlsFormatter;

Step 2: Add custom styling

Style the links to match your design:
.clickable-url {
  color: #1a0dab;
  text-decoration: underline;
  cursor: pointer;
}

.clickable-url:hover {
  color: #0056b3;
}

Step 3: Use the formatter

Pass it to message components:
import {
  CometChatMessageList,
  CometChatMessageComposer,
} from "@cometchat/chat-uikit-react";
import CometChatUrlsFormatter from "./CometChatUrlsFormatter";

function ChatWithLinks({ user }) {
  const urlFormatter = new CometChatUrlsFormatter();

  return (
    <div style={{ display: "flex", flexDirection: "column", height: "100vh" }}>
      <CometChatMessageList 
        user={user}
        textFormatters={[urlFormatter]}
      />
      <CometChatMessageComposer 
        user={user}
        textFormatters={[urlFormatter]}
      />
    </div>
  );
}

Step 4: Add click tracking

Override onUrlClick to add analytics:
private onUrlClick = (event: Event) => {
  const target = event.target as HTMLAnchorElement;
  const url = target.href;
  
  // Track the click
  analytics.track("link_clicked", {
    url,
    timestamp: new Date().toISOString(),
  });
  
  // Optionally prevent default and handle navigation
  // event.preventDefault();
  // window.open(url, '_blank');
};

Complete Example

import { useEffect, useState } from "react";
import {
  CometChatMessageList,
  CometChatMessageComposer,
  CometChatMessageHeader,
  CometChatTextFormatter,
} from "@cometchat/chat-uikit-react";
import { CometChat } from "@cometchat/chat-sdk-javascript";
import "@cometchat/chat-uikit-react/css-variables.css";

// URL Formatter implementation
class CometChatUrlsFormatter extends CometChatTextFormatter {
  constructor() {
    super();
    this.setRegexPatterns([/(https?:\/\/[^\s]+)/g]);
  }

  onRegexMatch(inputText: string): string {
    return this.formatUrls(inputText);
  }

  private formatUrls(text: string): string {
    return text.replace(
      /(https?:\/\/[^\s]+)/g,
      '<a href="$1" class="chat-link" target="_blank" rel="noopener noreferrer">$1</a>'
    );
  }

  registerEventListeners(element: HTMLElement, classList: DOMTokenList): HTMLElement {
    if (classList.contains("chat-link")) {
      element.addEventListener("click", this.onUrlClick);
    }
    return element;
  }

  private onUrlClick = (event: Event) => {
    const target = event.target as HTMLAnchorElement;
    console.log("Link clicked:", target.href);
  };

  getFormattedText(text: string): string {
    return this.formatUrls(text);
  }
}

// Chat component
function UrlFormatterChat() {
  const [user, setUser] = useState<CometChat.User>();
  const urlFormatter = new CometChatUrlsFormatter();

  useEffect(() => {
    CometChat.getUser("USER_UID").then(setUser);
  }, []);

  if (!user) return <div>Loading...</div>;

  return (
    <>
      <style>{`
        .chat-link {
          color: #6852d6;
          text-decoration: underline;
          cursor: pointer;
        }
        .chat-link:hover {
          color: #4a3a9e;
        }
      `}</style>
      <div style={{ height: "100vh", display: "flex", flexDirection: "column" }}>
        <CometChatMessageHeader user={user} />
        <div style={{ flex: 1, overflow: "hidden" }}>
          <CometChatMessageList 
            user={user}
            textFormatters={[urlFormatter]}
          />
        </div>
        <CometChatMessageComposer 
          user={user}
          textFormatters={[urlFormatter]}
        />
      </div>
    </>
  );
}

export default UrlFormatterChat;

Customization Options

/* Subtle links */
.chat-link {
  color: inherit;
  text-decoration: none;
  border-bottom: 1px dotted currentColor;
}

/* Button-style links */
.chat-link {
  display: inline-block;
  padding: 2px 8px;
  background: #e8e8e8;
  border-radius: 4px;
  text-decoration: none;
  color: #333;
}

Custom navigation

private onUrlClick = (event: Event) => {
  event.preventDefault();
  const target = event.target as HTMLAnchorElement;
  const url = target.href;
  
  // Open in custom modal or in-app browser
  openLinkPreview(url);
};

Common Issues

Always include rel="noopener noreferrer" on external links for security.
IssueSolution
Links not clickableCheck registerEventListeners is implemented
Styling not appliedVerify CSS class matches the one in formatUrls
Links opening in same tabAdd target="_blank" to anchor tags

Next Steps