From 5310529ee0becbc41351e599ecf9a5d9cbe51e15 Mon Sep 17 00:00:00 2001 From: mohamed magdy <40938625+mohamedmagdy17593@users.noreply.github.com> Date: Mon, 26 Jan 2026 15:07:27 +0000 Subject: [PATCH] =?UTF-8?q?=F0=9F=AA=A4=20refactor:=20Reset=20Interaction?= =?UTF-8?q?=20State=20When=20Mouse=20Leaves=20Conversation=20Item=20(#1140?= =?UTF-8?q?2)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix: reset hasInteracted state when mouse leaves conversation item * fix lint * refactor: update state setter types in ConvoOptions and DeleteButton components for Fixing types issue * fix: Add blur handler and focus-aware popover close for Conversation a11y --- client/src/components/Conversations/Convo.tsx | 37 ++++++++++++++++++- .../ConvoOptions/ConvoOptions.tsx | 2 +- .../ConvoOptions/DeleteButton.tsx | 4 +- 3 files changed, 39 insertions(+), 4 deletions(-) diff --git a/client/src/components/Conversations/Convo.tsx b/client/src/components/Conversations/Convo.tsx index a4d584a642..108755a291 100644 --- a/client/src/components/Conversations/Convo.tsx +++ b/client/src/components/Conversations/Convo.tsx @@ -47,6 +47,7 @@ export default function Conversation({ const [hasInteracted, setHasInteracted] = useState(false); const previousTitle = useRef(title); + const containerRef = useRef(null); useEffect(() => { if (title !== previousTitle.current) { @@ -109,6 +110,37 @@ export default function Conversation({ } }, [hasInteracted]); + const handleMouseLeave = useCallback(() => { + if (!isPopoverActive) { + setHasInteracted(false); + } + }, [isPopoverActive]); + + const handleBlur = useCallback( + (e: React.FocusEvent) => { + // Don't reset if focus is moving to a child element within this container + if (e.currentTarget.contains(e.relatedTarget as Node)) { + return; + } + if (!isPopoverActive) { + setHasInteracted(false); + } + }, + [isPopoverActive], + ); + + const handlePopoverOpenChange = useCallback((open: boolean) => { + setIsPopoverActive(open); + if (!open) { + requestAnimationFrame(() => { + const container = containerRef.current; + if (container && !container.contains(document.activeElement)) { + setHasInteracted(false); + } + }); + } + }, []); + const handleNavigation = (ctrlOrMetaKey: boolean) => { if (ctrlOrMetaKey) { toggleNav(); @@ -141,12 +173,13 @@ export default function Conversation({ isActiveConvo, conversationId, isPopoverActive, - setIsPopoverActive, + setIsPopoverActive: handlePopoverOpenChange, isShiftHeld: isActiveConvo ? isShiftHeld : false, }; return (
{ if (renaming) { return; diff --git a/client/src/components/Conversations/ConvoOptions/ConvoOptions.tsx b/client/src/components/Conversations/ConvoOptions/ConvoOptions.tsx index a7b0a780e7..25889e0e67 100644 --- a/client/src/components/Conversations/ConvoOptions/ConvoOptions.tsx +++ b/client/src/components/Conversations/ConvoOptions/ConvoOptions.tsx @@ -35,7 +35,7 @@ function ConvoOptions({ retainView: () => void; renameHandler: (e: MouseEvent) => void; isPopoverActive: boolean; - setIsPopoverActive: React.Dispatch>; + setIsPopoverActive: (open: boolean) => void; isActiveConvo: boolean; isShiftHeld?: boolean; }) { diff --git a/client/src/components/Conversations/ConvoOptions/DeleteButton.tsx b/client/src/components/Conversations/ConvoOptions/DeleteButton.tsx index 002d555455..17691b4a08 100644 --- a/client/src/components/Conversations/ConvoOptions/DeleteButton.tsx +++ b/client/src/components/Conversations/ConvoOptions/DeleteButton.tsx @@ -25,7 +25,7 @@ type DeleteButtonProps = { showDeleteDialog?: boolean; setShowDeleteDialog?: (value: boolean) => void; triggerRef?: React.RefObject; - setMenuOpen?: React.Dispatch>; + setMenuOpen?: (open: boolean) => void; }; export function DeleteConversationDialog({ @@ -35,7 +35,7 @@ export function DeleteConversationDialog({ retainView, title, }: { - setMenuOpen?: React.Dispatch>; + setMenuOpen?: (open: boolean) => void; setShowDeleteDialog: (value: boolean) => void; conversationId: string; retainView: () => void;