diff --git a/apps/app/src/components/sidebar/ThreadRow.test.tsx b/apps/app/src/components/sidebar/ThreadRow.test.tsx index 26b8000660..29f15ece72 100644 --- a/apps/app/src/components/sidebar/ThreadRow.test.tsx +++ b/apps/app/src/components/sidebar/ThreadRow.test.tsx @@ -305,6 +305,27 @@ describe("ThreadRow", () => { ); }); + it("starts thread bootstrap on keyboard focus before activation", () => { + const phase = createPerfPhaseLog(); + prefetchThreadDetailBootstrap.mockImplementation(() => { + phase.mark("bootstrap-prefetch"); + }); + renderThreadRow({ thread: createThread({ id: "thr_focus" }) }); + const link = screen.getByRole("link", { name: "Open Thread" }); + + fireEvent.focus(link); + phase.mark("focus-complete"); + fireEvent.keyDown(link, { key: "Enter" }); + phase.mark("activate-complete"); + + phase.expectBefore("bootstrap-prefetch", "focus-complete"); + phase.expectBefore("focus-complete", "activate-complete"); + expect(prefetchThreadDetailBootstrap).toHaveBeenCalledWith( + expect.anything(), + "thr_focus", + ); + }); + it("does not prefetch thread bootstrap on a non-primary pointer", () => { renderThreadRow({}); fireEvent.pointerDown(screen.getByRole("link", { name: "Open Thread" }), { diff --git a/apps/app/src/components/sidebar/ThreadRow.tsx b/apps/app/src/components/sidebar/ThreadRow.tsx index e14650ee24..799de5d619 100644 --- a/apps/app/src/components/sidebar/ThreadRow.tsx +++ b/apps/app/src/components/sidebar/ThreadRow.tsx @@ -699,6 +699,9 @@ function ThreadRowComponent({ to={getThreadRoutePath({ projectId, threadId: thread.id })} data-sidebar-thread-shortcut-target="" data-sidebar-thread-id={thread.id} + onFocus={() => { + prefetchThreadDetailBootstrap(queryClient, thread.id); + }} onClick={(event) => { if (isEditing) { event.preventDefault();