From 65651a0e862fdde8e9ab23e7c9530c55c3633243 Mon Sep 17 00:00:00 2001
From: BigSimmo <87357024+BigSimmo@users.noreply.github.com>
Date: Wed, 12 Aug 2026 13:43:50 +0800
Subject: [PATCH 1/2] fix(ui): restore phone suggestion ticker
---
src/components/ClinicalDashboard.tsx | 1 +
.../global-search-shell.tsx | 1 +
.../master-search-header.tsx | 4 +
.../universal-search-command-surface.tsx | 99 ++++++++++++++++---
tests/ui-overlap.spec.ts | 16 ++-
5 files changed, 109 insertions(+), 12 deletions(-)
diff --git a/src/components/ClinicalDashboard.tsx b/src/components/ClinicalDashboard.tsx
index 05fb92a664..f33ccf8e36 100644
--- a/src/components/ClinicalDashboard.tsx
+++ b/src/components/ClinicalDashboard.tsx
@@ -3366,6 +3366,7 @@ export function ClinicalDashboard({
composerFollowUpSuggestions={searchMode === "answer" ? answerFollowUpSuggestions : undefined}
onPickComposerFollowUpSuggestion={handlePickFollowUpSuggestion}
composerFollowUpSuggestionsDisabled={loading}
+ showPhoneSuggestionTickerOnHome={showSharedHome}
sharedHomeIdentity={showSharedHome}
composerPlaceholder={searchMode === "answer" && latestAnswerQuery ? "Ask a follow-up..." : undefined}
mobileSearchPlacement={hasMobileBottomSearch ? "bottom" : "default"}
diff --git a/src/components/clinical-dashboard/global-search-shell.tsx b/src/components/clinical-dashboard/global-search-shell.tsx
index 651a4cb0c3..84247b396a 100644
--- a/src/components/clinical-dashboard/global-search-shell.tsx
+++ b/src/components/clinical-dashboard/global-search-shell.tsx
@@ -877,6 +877,7 @@ function GlobalStandaloneSearchShellBody({
differentialsCompareAddonActive ? differentialsMobileCompareAddonSlotId : undefined
}
desktopSearchPlacement={desktopSearchPlacement === "hero" && isStandaloneModeHome ? "hero" : "default"}
+ showPhoneSuggestionTickerOnHome={isStandaloneModeHome || pathname === "/"}
searchComposerVisible={shouldShowSearchComposer}
desktopHomeComposerSlotId={isStandaloneModeHome ? modeHomeDesktopComposerSlotId : undefined}
desktopPageComposerSlotId={
diff --git a/src/components/clinical-dashboard/master-search-header.tsx b/src/components/clinical-dashboard/master-search-header.tsx
index 1cc6aa23e3..e87b6c29a8 100644
--- a/src/components/clinical-dashboard/master-search-header.tsx
+++ b/src/components/clinical-dashboard/master-search-header.tsx
@@ -195,6 +195,7 @@ export function MasterSearchHeader({
mobileBottomSearchVariant = "default",
desktopSearchPlacement = "default",
searchComposerVisible = true,
+ showPhoneSuggestionTickerOnHome = false,
desktopHomeComposerSlotId,
desktopPageComposerSlotId,
heroComposerBreakpoint = "all",
@@ -250,6 +251,8 @@ export function MasterSearchHeader({
* content keeps maximum screen space. Every phone dock uses it now; the
* "default" value remains for hosts that need the taller legacy dock. */
mobileBottomSearchVariant?: "default" | "compact";
+ /** Show the compact phone suggestion ticker only for standalone-mode homes. */
+ showPhoneSuggestionTickerOnHome?: boolean;
desktopSearchPlacement?: "default" | "hero";
searchComposerVisible?: boolean;
/** Mode-home slot the composer portals into so the search pill sits in the
@@ -1816,6 +1819,7 @@ export function MasterSearchHeader({
onListboxIdReady={setCommandListboxId}
onActiveItemIdChange={setCommandActiveItemId}
onFocusSearchInput={handleFocusSearchInput}
+ showPhoneSuggestionTicker={showPhoneSuggestionTickerOnHome}
>
void;
+}) {
const [activeExampleIndex, setActiveExampleIndex] = useState(0);
+ const [heldTickerExample, setHeldTickerExample] = useState
(null);
+ const [isTickerHeld, setIsTickerHeld] = useState(false);
const activeExample = examples[activeExampleIndex % examples.length];
useEffect(() => {
+ if (isTickerHeld) {
+ return;
+ }
+
if (examples.length <= 1) return;
const intervalId = window.setInterval(() => {
setActiveExampleIndex((current) => (current + 1) % examples.length);
}, SMART_HINT_ROTATION_MS);
return () => window.clearInterval(intervalId);
- }, [examples]);
+ }, [examples, isTickerHeld]);
+
+ const freezeTicker = useCallback(() => {
+ setHeldTickerExample(activeExample);
+ setIsTickerHeld(true);
+ }, [activeExample]);
+
+ const releaseTicker = useCallback(() => {
+ setIsTickerHeld(false);
+ }, []);
+
+ const resolvedTickerExample = isTickerHeld ? (heldTickerExample ?? activeExample) : activeExample;
if (!activeExample) return null;
return (
-
- Smart search
- ·
-
- Try “{activeExample}” in {modeLabel}.
-
-
+ <>
+
+ Smart search
+ ·
+
+ Try “{activeExample}” in {modeLabel}.
+
+
+ {showPhoneTicker ? (
+
+ ) : null}
+ >
);
}
@@ -364,6 +430,7 @@ export function UniversalSearchCommandSurface({
onFocusSearchInput,
onListboxIdReady,
onActiveItemIdChange,
+ showPhoneSuggestionTicker = false,
placement = "inline",
children,
}: {
@@ -384,6 +451,8 @@ export function UniversalSearchCommandSurface({
onFocusSearchInput?: () => void;
onListboxIdReady?: (listboxId: string) => void;
onActiveItemIdChange?: (activeItemId: string | null) => void;
+ /** Show the compact, tappable suggestion ticker below an in-flow phone home composer. */
+ showPhoneSuggestionTicker?: boolean;
placement?: CommandSurfacePlacement;
children: ReactNode;
}) {
@@ -992,7 +1061,15 @@ export function UniversalSearchCommandSurface({
placement === "bottom-dock" ? "gap-1" : "gap-2",
)}
>
-
+ {
+ onQueryChange(example);
+ onFocusSearchInput?.();
+ }}
+ />
{
diff --git a/tests/ui-overlap.spec.ts b/tests/ui-overlap.spec.ts
index 79923b3f6a..94ee44dbc1 100644
--- a/tests/ui-overlap.spec.ts
+++ b/tests/ui-overlap.spec.ts
@@ -266,12 +266,26 @@ test.describe("Header element overlap coverage", () => {
);
});
- test("phone smart search does not show the desktop rotating text or prompt row", async ({ page }) => {
+ test("phone smart search replaces desktop rows with one tappable ticker", async ({ page }) => {
await page.setViewportSize({ width: 390, height: 820 });
await mockDemoDashboard(page);
await gotoHome(page);
await expect(page.getByTestId("smart-search-rotating-text")).toBeHidden();
await expect(page.getByTestId("smart-search-prompt-row")).toBeHidden();
+
+ const ticker = page.getByTestId("smart-search-phone-ticker");
+ await expect(ticker).toBeVisible();
+ await expect(ticker).toContainText("Try this");
+ await expect(ticker).toContainText("Tap to search");
+
+ const tickerBox = await ticker.boundingBox();
+ expect(tickerBox, "phone suggestion ticker must render").not.toBeNull();
+ expect(tickerBox!.height, "phone ticker must meet the tap-target floor").toBeGreaterThanOrEqual(48);
+
+ const suggestion = (await ticker.getAttribute("aria-label"))?.replace("Try suggested search: ", "");
+ expect(suggestion).toBeTruthy();
+ await ticker.click();
+ await expect(page.locator('[data-testid="global-search-input"]:visible').first()).toHaveValue(suggestion ?? "");
});
});
From 8368bd3664afb4f919ebdddaf1ada25de18d51c5 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Wed, 12 Aug 2026 07:45:13 +0000
Subject: [PATCH 2/2] Fix phone suggestion ticker to show on all hero-owned
mode homes, not just /
Co-authored-by: BigSimmo <87357024+BigSimmo@users.noreply.github.com>
---
src/components/ClinicalDashboard.tsx | 2 +-
tests/ui-overlap.spec.ts | 17 +++++++++++++++++
2 files changed, 18 insertions(+), 1 deletion(-)
diff --git a/src/components/ClinicalDashboard.tsx b/src/components/ClinicalDashboard.tsx
index f33ccf8e36..1ec7998a20 100644
--- a/src/components/ClinicalDashboard.tsx
+++ b/src/components/ClinicalDashboard.tsx
@@ -3366,7 +3366,7 @@ export function ClinicalDashboard({
composerFollowUpSuggestions={searchMode === "answer" ? answerFollowUpSuggestions : undefined}
onPickComposerFollowUpSuggestion={handlePickFollowUpSuggestion}
composerFollowUpSuggestionsDisabled={loading}
- showPhoneSuggestionTickerOnHome={showSharedHome}
+ showPhoneSuggestionTickerOnHome={heroOwnsPhoneComposer}
sharedHomeIdentity={showSharedHome}
composerPlaceholder={searchMode === "answer" && latestAnswerQuery ? "Ask a follow-up..." : undefined}
mobileSearchPlacement={hasMobileBottomSearch ? "bottom" : "default"}
diff --git a/tests/ui-overlap.spec.ts b/tests/ui-overlap.spec.ts
index 94ee44dbc1..f04fb4bb7c 100644
--- a/tests/ui-overlap.spec.ts
+++ b/tests/ui-overlap.spec.ts
@@ -288,4 +288,21 @@ test.describe("Header element overlap coverage", () => {
await ticker.click();
await expect(page.locator('[data-testid="global-search-input"]:visible').first()).toHaveValue(suggestion ?? "");
});
+
+ test("phone suggestion ticker renders on /documents mode home", async ({ page }) => {
+ await page.setViewportSize({ width: 390, height: 820 });
+ await mockDemoDashboard(page);
+ await page.goto("/documents", { waitUntil: "domcontentloaded" });
+ await expect(async () => {
+ const header = page.locator("header#search");
+ await expect(header).toHaveCount(1);
+ await expect(header).toBeVisible();
+ }).toPass({ timeout: 30_000 });
+
+ const ticker = page.getByTestId("smart-search-phone-ticker");
+ await expect(ticker).toBeVisible();
+ const tickerBox = await ticker.boundingBox();
+ expect(tickerBox, "phone suggestion ticker must render on /documents home").not.toBeNull();
+ expect(tickerBox!.height, "phone ticker must meet the tap-target floor on /documents").toBeGreaterThanOrEqual(48);
+ });
});