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", {