From 448461532183b581ae7b80baa36c78a2b4716ba8 Mon Sep 17 00:00:00 2001 From: Mateusz Kwasniewski Date: Mon, 18 Sep 2023 14:42:41 +0200 Subject: [PATCH] fix: prevent blur when selecting text (#4762) --- frontend/src/component/common/Search/Search.tsx | 1 - frontend/src/hooks/useOnBlur.ts | 14 +++++++++++++- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/frontend/src/component/common/Search/Search.tsx b/frontend/src/component/common/Search/Search.tsx index 396d24d0ab..e13073c791 100644 --- a/frontend/src/component/common/Search/Search.tsx +++ b/frontend/src/component/common/Search/Search.tsx @@ -114,7 +114,6 @@ export const Search = ({ useKeyboardShortcut({ key: 'Escape' }, () => { if (searchContainerRef.current?.contains(document.activeElement)) { searchInputRef.current?.blur(); - hideSuggestions(); } }); const placeholder = `${customPlaceholder ?? 'Search'} (${hotkey})`; diff --git a/frontend/src/hooks/useOnBlur.ts b/frontend/src/hooks/useOnBlur.ts index 783ea9dd6b..4db97f9af4 100644 --- a/frontend/src/hooks/useOnBlur.ts +++ b/frontend/src/hooks/useOnBlur.ts @@ -5,24 +5,36 @@ export const useOnBlur = ( callback: () => void ): void => { useEffect(() => { + let mouseDownInside = false; + + const handleMouseDown = (event: MouseEvent) => { + mouseDownInside = + containerRef.current?.contains(event.target as Node) || false; + }; + const handleBlur = (event: FocusEvent) => { - // setTimeout is used because activeElement might not immediately be the new focused element after a blur event setTimeout(() => { if ( + !mouseDownInside && containerRef.current && !containerRef.current.contains(document.activeElement) ) { callback(); } + // Reset the flag for the next sequence of events. + mouseDownInside = false; }, 0); }; + document.addEventListener('mousedown', handleMouseDown); + const containerElement = containerRef.current; if (containerElement) { containerElement.addEventListener('blur', handleBlur, true); } return () => { + document.removeEventListener('mousedown', handleMouseDown); if (containerElement) { containerElement.removeEventListener('blur', handleBlur, true); }