diff --git a/ui/src/components/DocumentAnnotationPanel.tsx b/ui/src/components/DocumentAnnotationPanel.tsx index 97fd3edefe2..9c1773680bf 100644 --- a/ui/src/components/DocumentAnnotationPanel.tsx +++ b/ui/src/components/DocumentAnnotationPanel.tsx @@ -311,10 +311,10 @@ function AnnotationPanelBody(props: AnnotationPanelProps) { }, [props.open]); useEffect(() => { - if (!props.pendingAnchor || !props.open || props.isMobile) return; + if (!props.pendingAnchor || !props.open) return; if (isCoarsePointerDevice()) return; composerRef.current?.focus(); - }, [props.isMobile, props.open, props.pendingAnchor]); + }, [props.open, props.pendingAnchor]); // Keep the comment list congruent with the document: when a thread becomes // focused — whether by clicking its highlight in the doc or by adding a new diff --git a/ui/src/components/IssueDocumentAnnotations.test.tsx b/ui/src/components/IssueDocumentAnnotations.test.tsx index 176899f7d18..b5c6d5f2f3a 100644 --- a/ui/src/components/IssueDocumentAnnotations.test.tsx +++ b/ui/src/components/IssueDocumentAnnotations.test.tsx @@ -1059,6 +1059,54 @@ describe("IssueDocumentAnnotations", () => { } }); + it("auto-focuses the composer for fine-pointer requests in the narrow sheet layout", async () => { + const originalMatchMedia = window.matchMedia; + Object.defineProperty(window, "matchMedia", { + configurable: true, + value: vi.fn().mockImplementation((query: string) => ({ + matches: query === "(max-width: 1023px)", + media: query, + onchange: null, + addEventListener: vi.fn(), + removeEventListener: vi.fn(), + addListener: vi.fn(), + removeListener: vi.fn(), + dispatchEvent: vi.fn(), + })), + }); + const focusSpy = vi.spyOn(HTMLTextAreaElement.prototype, "focus").mockImplementation(() => {}); + mockAnnotationsApi.list.mockResolvedValue([]); + const root = createRoot(container); + const queryClient = makeQueryClient(); + const doc = makeDoc(); + + try { + await act(async () => { + root.render( + + + , + ); + }); + await flush(); + await flush(); + + const selectButton = container.querySelector('[data-testid="mock-annotation-selection"]'); + await act(async () => selectButton?.click()); + await flush(); + + expect(container.querySelector('[data-slot="sheet-content"]')).not.toBeNull(); + expect(container.querySelector('[data-testid="document-annotation-composer"]')).not.toBeNull(); + expect(focusSpy).toHaveBeenCalled(); + } finally { + focusSpy.mockRestore(); + Object.defineProperty(window, "matchMedia", { + configurable: true, + value: originalMatchMedia, + }); + } + }); + it("auto-focuses the composer for desktop selection requests", async () => { const originalMatchMedia = window.matchMedia; Object.defineProperty(window, "matchMedia", {