fix(email threads): linkify Email body so that URL links are properly formatted (#16415)

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

<img width="395" height="699" alt="Screenshot 2025-12-09 at 12 25 03 PM"
src="https://github.com/user-attachments/assets/772e6d03-8c48-45a1-985c-f775bbd3465c"
/>


### After
URLs are shown as link and are clickable now.

<img width="367" height="641" alt="Screenshot 2025-12-09 at 2 50 29 PM"
src="https://github.com/user-attachments/assets/d15bf23a-7cae-4cd4-b9da-e99706c7db38"
/>

<img width="376" height="656" alt="Screenshot 2025-12-09 at 2 50 46 PM"
src="https://github.com/user-attachments/assets/ba112a65-7550-47e3-b42f-83b94c08bfa6"
/>

---------

Co-authored-by: Lucas Bordeau <bordeau.lucas@gmail.com>
This commit is contained in:
Abhishek Kumar
2025-12-30 22:19:31 +05:30
committed by GitHub
parent 64d75d0b79
commit 61addf8b62
3 changed files with 38 additions and 2 deletions
@@ -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 (
<AnimatedEaseInOut isOpen={isDisplayed} duration="fast">
<StyledThreadMessageBody>{body}</StyledThreadMessageBody>
<StyledThreadMessageBody>
<Linkify
options={{
target: '_blank',
rel: 'noopener noreferrer',
}}
>
{body}
</Linkify>
</StyledThreadMessageBody>
</AnimatedEaseInOut>
);
};