From 1f95987750ea43297ffe75e39b0fb8210a1a6b0b Mon Sep 17 00:00:00 2001 From: BigSimmo <87357024+BigSimmo@users.noreply.github.com> Date: Mon, 6 Jul 2026 02:48:21 +0800 Subject: [PATCH 1/2] Defer phone search suggestions until user types --- .../universal-search-command-surface.tsx | 27 ++++++++++++++++++- tests/ui-tools.spec.ts | 9 +++++-- 2 files changed, 33 insertions(+), 3 deletions(-) diff --git a/src/components/clinical-dashboard/universal-search-command-surface.tsx b/src/components/clinical-dashboard/universal-search-command-surface.tsx index c2411c6240..c18cdeb5e4 100644 --- a/src/components/clinical-dashboard/universal-search-command-surface.tsx +++ b/src/components/clinical-dashboard/universal-search-command-surface.tsx @@ -5,6 +5,7 @@ import { useEffect, useId, useMemo, + useRef, useState, useSyncExternalStore, type KeyboardEvent as ReactKeyboardEvent, @@ -346,8 +347,14 @@ export function UniversalSearchCommandSurface({ const listboxId = useId(); const [activeIndex, setActiveIndex] = useState(-1); const trimmedQuery = query.trim(); + const requiresTypedQueryToOpen = placement === "bottom-dock"; + const composerFocusedRef = useRef(false); const mode = appModeDefinition(modeId); + function canOpenDropdownNow() { + return !requiresTypedQueryToOpen || trimmedQuery.length > 0; + } + const showSafetyBanner = modeId === "differentials" && differentialRedFlagTerms.some((term) => trimmedQuery.toLowerCase().includes(term)); const showFormCodeHint = modeId === "forms" && isFormCodeQuery(trimmedQuery); @@ -548,12 +555,14 @@ export function UniversalSearchCommandSurface({ function handleComposerKeyDown(event: ReactKeyboardEvent) { if (event.key === "ArrowDown") { event.preventDefault(); + if (!canOpenDropdownNow()) return; onDropdownOpenChange(true); setActiveIndex((current) => (current + 1) % Math.max(flatItems.length, 1)); return; } if (event.key === "ArrowUp") { event.preventDefault(); + if (!canOpenDropdownNow()) return; onDropdownOpenChange(true); setActiveIndex((current) => (current <= 0 ? flatItems.length - 1 : current - 1)); return; @@ -585,6 +594,16 @@ export function UniversalSearchCommandSurface({ onListboxIdReady?.(listboxId); }, [listboxId, onListboxIdReady]); + useEffect(() => { + if (requiresTypedQueryToOpen && composerFocusedRef.current && trimmedQuery.length > 0) { + onDropdownOpenChange(true); + } + if (requiresTypedQueryToOpen && trimmedQuery.length === 0) { + onDropdownOpenChange(false); + setActiveIndex(-1); + } + }, [requiresTypedQueryToOpen, trimmedQuery, onDropdownOpenChange]); + useEffect(() => { function handleSlashFocus(event: KeyboardEvent) { if (event.key !== "/" || event.metaKey || event.ctrlKey || event.altKey) return; @@ -628,8 +647,14 @@ export function UniversalSearchCommandSurface({ handleComposerKeyDown(event as unknown as ReactKeyboardEvent); } }} - onFocusCapture={() => onDropdownOpenChange(true)} + onFocusCapture={() => { + composerFocusedRef.current = true; + if (canOpenDropdownNow()) { + onDropdownOpenChange(true); + } + }} onBlurCapture={(event) => { + composerFocusedRef.current = false; if (!event.currentTarget.contains(event.relatedTarget as Node | null)) { onDropdownOpenChange(false); setActiveIndex(-1); diff --git a/tests/ui-tools.spec.ts b/tests/ui-tools.spec.ts index 3037cfaa43..be00c9834e 100644 --- a/tests/ui-tools.spec.ts +++ b/tests/ui-tools.spec.ts @@ -97,14 +97,19 @@ async function commandSurfaceOpensAbovePill(page: Page, hintPattern: RegExp) { { timeout: 10_000 }, ); await input.click(); + await input.fill(""); + await expect(page.getByRole("listbox")).toHaveCount(0); + await input.press("ArrowDown"); + await expect(page.getByRole("listbox")).toHaveCount(0); + + await input.fill("li"); await expect(async () => { - await input.press("ArrowDown"); - await expect(page.getByText(hintPattern)).toBeVisible(); await expect(page.getByRole("listbox").first()).toBeVisible(); }).toPass({ timeout: 15_000 }); const listbox = page.getByRole("listbox").first(); await expect(listbox).toBeVisible(); + await expect(page.getByText(hintPattern).first()).toBeVisible(); const geometry = await page.evaluate(() => { const pill = document.querySelector(".answer-footer-search-pill"); From 40fbc3e96df7fc9063caead42c9427d7d6d64796 Mon Sep 17 00:00:00 2001 From: Cursor Agent Date: Sun, 5 Jul 2026 23:56:45 +0000 Subject: [PATCH 2/2] Fix vector fallback global scope and phone-only suggestion deferral - Pass allowGlobalSearch through document-scoped vector fallback RPCs - Scope requiresTypedQueryToOpen to phone footer dock, not all bottom-dock --- src/components/clinical-dashboard/master-search-header.tsx | 1 + .../clinical-dashboard/universal-search-command-surface.tsx | 3 ++- src/lib/rag.ts | 2 +- 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/components/clinical-dashboard/master-search-header.tsx b/src/components/clinical-dashboard/master-search-header.tsx index cea7e6bcb5..d80793aa91 100644 --- a/src/components/clinical-dashboard/master-search-header.tsx +++ b/src/components/clinical-dashboard/master-search-header.tsx @@ -1248,6 +1248,7 @@ export function MasterSearchHeader({ recentQueries={recentQueries} commandScopes={commandScopes} placement={commandSurfacePlacement} + requiresTypedQueryToOpen={usesPhoneFooterDock} dropdownOpen={commandDropdownOpen} onDropdownOpenChange={setCommandDropdownOpen} onQueryChange={onQueryChange} diff --git a/src/components/clinical-dashboard/universal-search-command-surface.tsx b/src/components/clinical-dashboard/universal-search-command-surface.tsx index 6be914e956..6089a1b81d 100644 --- a/src/components/clinical-dashboard/universal-search-command-surface.tsx +++ b/src/components/clinical-dashboard/universal-search-command-surface.tsx @@ -269,6 +269,7 @@ export function UniversalSearchCommandSurface({ onFocusSearchInput, onListboxIdReady, placement = "inline", + requiresTypedQueryToOpen = false, children, }: { modeId: AppModeId; @@ -287,13 +288,13 @@ export function UniversalSearchCommandSurface({ onFocusSearchInput?: () => void; onListboxIdReady?: (listboxId: string) => void; placement?: CommandSurfacePlacement; + requiresTypedQueryToOpen?: boolean; children: ReactNode; }) { const config = searchCommandSurfaceConfig(modeId); const listboxId = useId(); const [activeIndex, setActiveIndex] = useState(-1); const trimmedQuery = query.trim(); - const requiresTypedQueryToOpen = placement === "bottom-dock"; const composerFocusedRef = useRef(false); const mode = appModeDefinition(modeId); diff --git a/src/lib/rag.ts b/src/lib/rag.ts index e0afa8b456..29b7df1d9e 100644 --- a/src/lib/rag.ts +++ b/src/lib/rag.ts @@ -5940,7 +5940,7 @@ export async function searchChunksWithTelemetry(args: SearchChunksArgs) { owner_filter: ownerScopeForDocumentFilteredRetrieval( args.ownerId, documentFilter ? [documentFilter] : undefined, - documentFilter ? undefined : args.allowGlobalSearch, + args.allowGlobalSearch, ), });