diff --git a/client/src/components/Assistant/AssistantHeader.tsx b/client/src/components/Assistant/AssistantHeader.tsx index 7cc74950a..5f79e954b 100644 --- a/client/src/components/Assistant/AssistantHeader.tsx +++ b/client/src/components/Assistant/AssistantHeader.tsx @@ -11,7 +11,7 @@ import { Trash2, X, } from 'lucide-react'; -import { type HTMLAttributes, type MouseEvent, useState } from 'react'; +import { type HTMLAttributes, type MouseEvent, useRef, useState } from 'react'; import { useNavigate } from 'react-router'; import { useTranslation } from '../../i18n'; @@ -79,6 +79,7 @@ export default function AssistantHeader({ const [memoryOpen, setMemoryOpen] = useState(false); const navigate = useNavigate(); const menu = useContextMenu(); + const moreRef = useRef(null); const [confirming, setConfirming] = useState(false); const threads = thread.threads ?? []; const history = usePopoverList(threads.findIndex((th) => th.id === thread.threadId) + 1); @@ -95,6 +96,14 @@ export default function AssistantHeader({ run(); }; + // Closed by Escape or a pick while it holds the focus, the menu hands it back to its button, so the keys + // go on reaching the window; a click or a scroll elsewhere leaves the focus where it went. + const closeMenu = () => { + const fromMenu = document.activeElement?.closest('[role="menu"]') != null; + menu.close(); + if (fromMenu) moreRef.current?.focus(); + }; + const openMenu = (e: MouseEvent) => menu.open( e, @@ -187,10 +196,12 @@ export default function AssistantHeader({