From 61addf8b62f505f2e4d93ba5addb2d63be2e183c Mon Sep 17 00:00:00 2001 From: Abhishek Kumar Date: Tue, 30 Dec 2025 22:19:31 +0530 Subject: [PATCH] fix(email threads): linkify Email body so that URL links are properly formatted (#16415) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Closes #16396 Added [linkify-react](https://www.npmjs.com/package/linkify-react) and [linkifyjs](https://www.npmjs.com/package/linkifyjs?activeTab=versions) to dependancies. Both are widely used libraries with millions of weekly downloads. Both of them have 0 dependancies on other packages, so should be safe to use. ### Before URLs were shown as plain text Screenshot 2025-12-09 at 12 25 03 PM ### After URLs are shown as link and are clickable now. Screenshot 2025-12-09 at 2 50 29 PM Screenshot 2025-12-09 at 2 50 46 PM --------- Co-authored-by: Lucas Bordeau --- packages/twenty-front/package.json | 2 ++ .../components/EmailThreadMessageBody.tsx | 24 ++++++++++++++++++- yarn.lock | 14 ++++++++++- 3 files changed, 38 insertions(+), 2 deletions(-) diff --git a/packages/twenty-front/package.json b/packages/twenty-front/package.json index 4166e8d750..5f275c9aa9 100644 --- a/packages/twenty-front/package.json +++ b/packages/twenty-front/package.json @@ -88,6 +88,8 @@ "json-2-csv": "^5.4.0", "json-logic-js": "^2.0.5", "jwt-decode": "^4.0.0", + "linkify-react": "^4.1.3", + "linkifyjs": "^4.1.3", "qs": "^6.11.2", "react-data-grid": "7.0.0-beta.13", "react-datepicker": "^6.7.1", diff --git a/packages/twenty-front/src/modules/activities/emails/components/EmailThreadMessageBody.tsx b/packages/twenty-front/src/modules/activities/emails/components/EmailThreadMessageBody.tsx index 4a0a966054..438504018f 100644 --- a/packages/twenty-front/src/modules/activities/emails/components/EmailThreadMessageBody.tsx +++ b/packages/twenty-front/src/modules/activities/emails/components/EmailThreadMessageBody.tsx @@ -1,5 +1,6 @@ import styled from '@emotion/styled'; import { motion } from 'framer-motion'; +import Linkify from 'linkify-react'; import { AnimatedEaseInOut } from 'twenty-ui/utilities'; const StyledThreadMessageBody = styled(motion.div)` @@ -9,6 +10,18 @@ const StyledThreadMessageBody = styled(motion.div)` margin-top: ${({ theme }) => theme.spacing(4)}; white-space: pre-line; overflow-wrap: break-word; + + a { + color: ${({ theme }) => theme.font.color.primary}; + + text-decoration: underline; + text-decoration-color: ${({ theme }) => theme.font.color.primary}; + + &:hover { + color: ${({ theme }) => theme.font.color.tertiary}; + text-decoration-color: ${({ theme }) => theme.border.color.strong}; + } + } `; type EmailThreadMessageBodyProps = { @@ -22,7 +35,16 @@ export const EmailThreadMessageBody = ({ }: EmailThreadMessageBodyProps) => { return ( - {body} + + + {body} + + ); }; diff --git a/yarn.lock b/yarn.lock index 92a2d08fa8..07ed02a916 100644 --- a/yarn.lock +++ b/yarn.lock @@ -42669,7 +42669,17 @@ __metadata: languageName: node linkType: hard -"linkifyjs@npm:^4.2.0, linkifyjs@npm:^4.3.2": +"linkify-react@npm:^4.1.3": + version: 4.3.2 + resolution: "linkify-react@npm:4.3.2" + peerDependencies: + linkifyjs: ^4.0.0 + react: ">= 15.0.0" + checksum: 10c0/6f1e5fa28129bfa2c9fe7568a63c4cc8453cfa7de9f401a33b9bf6826b8d7ecccbb054cfe54c0b3f7c39d36b410189a9adcf438667c3e6443afda8bd2e4b36df + languageName: node + linkType: hard + +"linkifyjs@npm:^4.1.3, linkifyjs@npm:^4.2.0, linkifyjs@npm:^4.3.2": version: 4.3.2 resolution: "linkifyjs@npm:4.3.2" checksum: 10c0/1a85e6b368304a4417567fe5e38651681e3e82465590836942d1b4f3c834cc35532898eb1e2479f6337d9144b297d418eb708b6be8ed0b3dc3954a3588e07971 @@ -56708,6 +56718,8 @@ __metadata: json-2-csv: "npm:^5.4.0" json-logic-js: "npm:^2.0.5" jwt-decode: "npm:^4.0.0" + linkify-react: "npm:^4.1.3" + linkifyjs: "npm:^4.1.3" monaco-editor: "npm:^0.51.0" monaco-editor-auto-typings: "npm:^0.4.5" optionator: "npm:^0.9.1"