diff --git a/frontend-new/src/chat/chatMessage/components/chatBubble/ChatBubble.stories.tsx b/frontend-new/src/chat/chatMessage/components/chatBubble/ChatBubble.stories.tsx index 65feccdb0..ba8424dc0 100644 --- a/frontend-new/src/chat/chatMessage/components/chatBubble/ChatBubble.stories.tsx +++ b/frontend-new/src/chat/chatMessage/components/chatBubble/ChatBubble.stories.tsx @@ -35,3 +35,17 @@ export const ShownWithFooter: Story = { children: , }, }; + +export const WithClickableLinks: Story = { + args: { + message: + "Here are some opportunities that match you:\n\n" + + "1. Junior Baker\n" + + " Employer: Sunrise Bakery\n" + + " Apply here: https://jobs.example.com/junior-baker\n\n" + + "2. Pastry Assistant\n" + + " Employer: City Cafe\n" + + " Apply here: www.citycafe.co.ke/careers/pastry-assistant", + sender: ConversationMessageSender.COMPASS, + }, +}; diff --git a/frontend-new/src/chat/chatMessage/components/chatBubble/ChatBubble.tsx b/frontend-new/src/chat/chatMessage/components/chatBubble/ChatBubble.tsx index 2f11289d0..157069aec 100644 --- a/frontend-new/src/chat/chatMessage/components/chatBubble/ChatBubble.tsx +++ b/frontend-new/src/chat/chatMessage/components/chatBubble/ChatBubble.tsx @@ -1,6 +1,25 @@ import React from "react"; import { ConversationMessageSender } from "src/chat/ChatService/ChatService.types"; -import { Box, Typography, styled } from "@mui/material"; +import { Box, Link, Typography, styled } from "@mui/material"; + +// Matches http(s) URLs and www. URLs, stopping at whitespace or common trailing punctuation. +const URL_REGEX = /((?:https?:\/\/|www\.)[^\s<]+[^\s<.,;:!?)\]}'"])/gi; + +// Splits a plain-text message into text and clickable link segments, preserving the original text. +const renderTextWithLinks = (text: string): React.ReactNode => { + const parts = text.split(URL_REGEX); + return parts.map((part, index) => { + if (index % 2 === 1) { + const href = part.startsWith("www.") ? `https://${part}` : part; + return ( + + {part} + + ); + } + return part; + }); +}; export interface ChatBubbleProps { message: string | React.ReactNode; @@ -39,7 +58,7 @@ const ChatBubble: React.FC = ({ message, sender, children }) => return ( - {message} + {typeof message === "string" ? renderTextWithLinks(message) : message} {children}