From 7a51e177132ebd431aa993eee3d715dd999585ce Mon Sep 17 00:00:00 2001 From: David Garcia <1156404+david12341235@users.noreply.github.com> Date: Mon, 15 Sep 2025 15:17:52 -0700 Subject: [PATCH 1/2] Add optional userSelect property to FunEmoji and enable in MessageTextRenderer. Allows user text selection to start on an emoji. Fixes https://github.com/signalapp/Signal-Desktop/issues/7206 --- ts/components/conversation/Emojify.tsx | 3 +++ ts/components/conversation/MessageTextRenderer.tsx | 1 + ts/components/fun/FunEmoji.tsx | 2 ++ 3 files changed, 6 insertions(+) diff --git a/ts/components/conversation/Emojify.tsx b/ts/components/conversation/Emojify.tsx index 25a3097275..57231c08e8 100644 --- a/ts/components/conversation/Emojify.tsx +++ b/ts/components/conversation/Emojify.tsx @@ -23,6 +23,7 @@ export type Props = { isInvisible?: boolean; /** Allows you to customize now non-newlines are rendered. Simplest is just a . */ renderNonEmoji?: RenderTextCallbackType; + selectable?: boolean; }; const defaultRenderNonEmoji: RenderTextCallbackType = ({ text }) => text; @@ -31,6 +32,7 @@ export function Emojify({ fontSizeOverride, text, renderNonEmoji = defaultRenderNonEmoji, + selectable = false, }: Props): JSX.Element { const emojiLocalizer = useFunEmojiLocalizer(); return ( @@ -59,6 +61,7 @@ export function Emojify({ aria-label={emojiLocalizer.getLocaleShortName(variantKey)} emoji={variant} size={fontSizeOverride} + selectable={selectable} /> ); } diff --git a/ts/components/conversation/MessageTextRenderer.tsx b/ts/components/conversation/MessageTextRenderer.tsx index b922126e88..52999ec819 100644 --- a/ts/components/conversation/MessageTextRenderer.tsx +++ b/ts/components/conversation/MessageTextRenderer.tsx @@ -431,6 +431,7 @@ function renderText({ )} fontSizeOverride={jumboEmojiSize} text={text} + selectable /> ); } diff --git a/ts/components/fun/FunEmoji.tsx b/ts/components/fun/FunEmoji.tsx index ddb30bf6d8..ca354e1349 100644 --- a/ts/components/fun/FunEmoji.tsx +++ b/ts/components/fun/FunEmoji.tsx @@ -137,6 +137,7 @@ export type FunInlineEmojiProps = FunImageAriaProps & Readonly<{ size?: number | null; emoji: EmojiVariantData; + selectable?: boolean; }>; export function FunInlineEmoji(props: FunInlineEmojiProps): JSX.Element { @@ -183,6 +184,7 @@ export function FunInlineEmoji(props: FunInlineEmojiProps): JSX.Element { '--fun-emoji-sheet-x': props.emoji.sheetX, '--fun-emoji-sheet-y': props.emoji.sheetY, '--fun-emoji-jumbo-image': jumboImage, + ...(props.selectable && { userSelect: 'text' }), } as CSSProperties } /> From 6337742628cf576a9ee289f2957f0a7ae8bbf7bb Mon Sep 17 00:00:00 2001 From: David Garcia <1156404+david12341235@users.noreply.github.com> Date: Mon, 22 Sep 2025 08:46:37 -0700 Subject: [PATCH 2/2] Added "user-select: inherit" to .FunInlineEmoji based on PR feedback --- stylesheets/components/fun/FunEmoji.scss | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/stylesheets/components/fun/FunEmoji.scss b/stylesheets/components/fun/FunEmoji.scss index ea029fd5b0..c40da41f51 100644 --- a/stylesheets/components/fun/FunEmoji.scss +++ b/stylesheets/components/fun/FunEmoji.scss @@ -161,7 +161,12 @@ $inline-emoji-container-name: inline-emoji; margin-bottom: round(-0.4em + 1px, 1px); vertical-align: baseline; content-visibility: auto; - user-select: none; + // We want to inherit here since most usage of should not be + // selectable, but in cases like messages, conversation titles/descriptions, + // etc we want emoji to be selectable within the surrounding text. + // If the root `.FunInlineEmoji` element isn't selectable, then selection + // can't start on the emoji itself. + user-select: inherit; } .FunEmojiSelectionText {