diff --git a/src/renderer/features/agents/main/active-chat.tsx b/src/renderer/features/agents/main/active-chat.tsx index cf85ed17..ccd5b266 100644 --- a/src/renderer/features/agents/main/active-chat.tsx +++ b/src/renderer/features/agents/main/active-chat.tsx @@ -3793,15 +3793,20 @@ const ChatViewInner = memo(function ChatViewInner({ if (!isActive) return if (isMobile) return // Don't autofocus on mobile - // Use requestAnimationFrame to ensure DOM is ready after render - requestAnimationFrame(() => { + // Use setTimeout to ensure focus happens after all React DOM updates + // and browser focus management has settled. requestAnimationFrame alone + // is too early when the terminal is open — the xterm textarea retains + // focus and the editor's focus() call doesn't stick. + const timeoutId = setTimeout(() => { // Skip if sidebar keyboard navigation is active (user is arrowing through sidebar items) if (appStore.get(suppressInputFocusAtom)) { appStore.set(suppressInputFocusAtom, false) return } editorRef.current?.focus() - }) + }, 100) + + return () => clearTimeout(timeoutId) }, [isActive, subChatId, isMobile]) // Refs for handleSend to avoid recreating callback on every messages change diff --git a/src/renderer/features/agents/ui/agent-user-message-bubble.tsx b/src/renderer/features/agents/ui/agent-user-message-bubble.tsx index 37938c7b..b2a2345d 100644 --- a/src/renderer/features/agents/ui/agent-user-message-bubble.tsx +++ b/src/renderer/features/agents/ui/agent-user-message-bubble.tsx @@ -12,6 +12,7 @@ import { import { AgentImageItem } from "./agent-image-item" import { RenderFileMentions, extractTextMentions, TextMentionBlocks } from "../mentions/render-file-mentions" import { useSearchHighlight, useSearchQuery } from "../search" +import { useAgentSubChatStore } from "../stores/sub-chat-store" interface AgentUserMessageBubbleProps { messageId: string @@ -119,6 +120,14 @@ export const AgentUserMessageBubble = memo(function AgentUserMessageBubble({ const [isExpanded, setIsExpanded] = useState(false) const contentRef = useRef(null) + // Close expanded dialog when user switches sub-chat tabs. + // The Dialog portals to document.body, so it escapes the hidden tab's + // opacity:0 / pointerEvents:none container and would remain visible. + const activeSubChatId = useAgentSubChatStore((s) => s.activeSubChatId) + useEffect(() => { + setIsExpanded(false) + }, [activeSubChatId]) + // Extract quote/diff mentions to display above the bubble const { textMentions, cleanedText } = useMemo( () => extractTextMentions(textContent),