From 8116d12c15495fa192e92f5bfb75cb561bb16402 Mon Sep 17 00:00:00 2001 From: Eric Bailey Date: Fri, 20 Dec 2024 13:59:33 -0600 Subject: Fix Emoji picker focus (#7217) * Only portal the emoji picker where needed * Add optional portal prop to emoji picker * Use FocusScope to our advantage * Pare back, add guards, fix focus trap * Don't return focus to emoji button * Set DM input position on emoji insert * Let the caller determine next focus node --------- Co-authored-by: Dan Abramov --- .../Messages/components/MessageInput.web.tsx | 28 +++++++++++++++++----- 1 file changed, 22 insertions(+), 6 deletions(-) (limited to 'src/screens/Messages/components/MessageInput.web.tsx') diff --git a/src/screens/Messages/components/MessageInput.web.tsx b/src/screens/Messages/components/MessageInput.web.tsx index 72e0382a9..bac163685 100644 --- a/src/screens/Messages/components/MessageInput.web.tsx +++ b/src/screens/Messages/components/MessageInput.web.tsx @@ -3,6 +3,7 @@ import {Pressable, StyleSheet, View} from 'react-native' import {msg} from '@lingui/macro' import {useLingui} from '@lingui/react' import Graphemer from 'graphemer' +import {flushSync} from 'react-dom' import TextareaAutosize from 'react-textarea-autosize' import {isSafari, isTouchDevice} from '#/lib/browser' @@ -106,11 +107,19 @@ export function MessageInput({ const onEmojiInserted = React.useCallback( (emoji: Emoji) => { - const position = textAreaRef.current?.selectionStart ?? 0 - setMessage( - message => - message.slice(0, position) + emoji.native + message.slice(position), - ) + if (!textAreaRef.current) { + return + } + const position = textAreaRef.current.selectionStart ?? 0 + textAreaRef.current.focus() + flushSync(() => { + setMessage( + message => + message.slice(0, position) + emoji.native + message.slice(position), + ) + }) + textAreaRef.current.selectionStart = position + emoji.native.length + textAreaRef.current.selectionEnd = position + emoji.native.length }, [setMessage], ) @@ -148,7 +157,14 @@ export function MessageInput({