diff --git a/src/app/globals.css b/src/app/globals.css
index 9de9d6703e..409fa258a1 100644
--- a/src/app/globals.css
+++ b/src/app/globals.css
@@ -1238,16 +1238,39 @@ summary::-webkit-details-marker {
min-width: 0;
}
+.smart-search-rotating-text,
+.smart-search-prompt-row,
.smart-search-suggestion-row {
display: none;
}
@media (min-width: 1024px) {
+ .smart-search-rotating-text {
+ display: flex;
+ }
+
+ .smart-search-prompt-row,
.smart-search-suggestion-row {
display: flex;
}
}
+.smart-search-rotating-text {
+ min-height: 1.5rem;
+ align-items: center;
+ justify-content: center;
+ gap: 0.35rem;
+ padding-inline: 0.25rem;
+ color: var(--text-soft);
+ font-size: 0.75rem;
+ font-weight: 700;
+ letter-spacing: 0.01em;
+}
+
+.smart-search-rotating-query {
+ color: var(--clinical-accent);
+}
+
.answer-suggestion-label {
color: var(--text-soft);
font-size: 0.6875rem;
diff --git a/src/components/clinical-dashboard/universal-search-command-surface.tsx b/src/components/clinical-dashboard/universal-search-command-surface.tsx
index 3052409011..2252c2c7e3 100644
--- a/src/components/clinical-dashboard/universal-search-command-surface.tsx
+++ b/src/components/clinical-dashboard/universal-search-command-surface.tsx
@@ -22,6 +22,8 @@ import {
const focusRing =
"focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-[color:var(--focus)]";
+const SMART_HINT_ROTATION_MS = 3200;
+
type DropdownItem = {
id: string;
label: string;
@@ -54,15 +56,40 @@ function OptionShell({ active, children, hint }: { active: boolean; children: Re
export type CommandSurfacePlacement = "bottom-dock" | "inline";
-function ContextHintRow({ examples, onPickExample }: { examples: string[]; onPickExample: (example: string) => void }) {
+function SmartRotatingHint({ examples, modeLabel }: { examples: string[]; modeLabel: string }) {
+ const [activeExampleIndex, setActiveExampleIndex] = useState(0);
+ const activeExample = examples[activeExampleIndex % examples.length];
+
+ useEffect(() => {
+ if (examples.length <= 1) return;
+ const intervalId = window.setInterval(() => {
+ setActiveExampleIndex((current) => (current + 1) % examples.length);
+ }, SMART_HINT_ROTATION_MS);
+ return () => window.clearInterval(intervalId);
+ }, [examples]);
+
+ if (!activeExample) return null;
+
+ return (
+
+ Smart search
+ ยท
+
+ Try “{activeExample}” in {modeLabel}.
+
+
+ );
+}
+
+function SmartPromptRow({ examples, onPickExample }: { examples: string[]; onPickExample: (example: string) => void }) {
return (
);
}
@@ -545,14 +572,7 @@ export function UniversalSearchCommandSurface({
placement === "bottom-dock" ? "gap-1" : "gap-2",
)}
>
- {
- onQueryChange(example);
- onDropdownOpenChange(true);
- onFocusSearchInput?.();
- }}
- />
+
{
@@ -585,6 +605,14 @@ export function UniversalSearchCommandSurface({
/>
) : null}
+ {
+ onQueryChange(example);
+ onDropdownOpenChange(true);
+ onFocusSearchInput?.();
+ }}
+ />
diff --git a/tests/ui-overlap.spec.ts b/tests/ui-overlap.spec.ts
index 22a8d994e8..a9fc0fd403 100644
--- a/tests/ui-overlap.spec.ts
+++ b/tests/ui-overlap.spec.ts
@@ -154,41 +154,55 @@ test.describe("Header element overlap coverage", () => {
});
}
- test("desktop smart search keeps suggested words above the composer", async ({ page }) => {
+ test("desktop smart search keeps rotating text above and prompts below the composer", async ({ page }) => {
await page.setViewportSize({ width: 1280, height: 900 });
await mockDemoDashboard(page);
await gotoHome(page);
- const suggestionRow = page.getByTestId("smart-search-suggestion-row");
- await expect(suggestionRow).toBeVisible();
- await expect(suggestionRow.getByRole("button", { name: "lithium level timing" })).toBeVisible();
- await expect(suggestionRow.getByRole("button", { name: "clozapine ANC monitoring" })).toBeVisible();
+ const rotatingText = page.getByTestId("smart-search-rotating-text");
+ const promptRow = page.getByTestId("smart-search-prompt-row");
+ await expect(rotatingText).toBeVisible();
+ await expect(rotatingText).toContainText("Smart search");
+ await expect(promptRow).toBeVisible();
+ await expect(promptRow.getByRole("button", { name: "lithium level timing" })).toBeVisible();
+ await expect(promptRow.getByRole("button", { name: "clozapine ANC monitoring" })).toBeVisible();
const geometry = await page.evaluate(() => {
- const row = document.querySelector('[data-testid="smart-search-suggestion-row"]');
- const input = document.querySelector('[data-testid="global-search-input"]');
- if (!row || !input) return null;
- const rowRect = row.getBoundingClientRect();
- const inputRect = input.getBoundingClientRect();
- return { rowBottom: rowRect.bottom, inputTop: inputRect.top };
+ const hint = document.querySelector('[data-testid="smart-search-rotating-text"]');
+ const prompt = document.querySelector('[data-testid="smart-search-prompt-row"]');
+ const pill = document.querySelector(".answer-footer-search-pill");
+ if (!hint || !prompt || !pill) return null;
+ const hintRect = hint.getBoundingClientRect();
+ const promptRect = prompt.getBoundingClientRect();
+ const pillRect = pill.getBoundingClientRect();
+ return {
+ hintBottom: hintRect.bottom,
+ pillTop: pillRect.top,
+ pillBottom: pillRect.bottom,
+ promptTop: promptRect.top,
+ };
});
- expect(geometry, "suggestion row and smart search input must render").not.toBeNull();
- expect(geometry!.rowBottom, "suggestions should sit above the smart search bar").toBeLessThanOrEqual(
- geometry!.inputTop + 1,
+ expect(geometry, "smart search hint, composer, and prompt row must render").not.toBeNull();
+ expect(geometry!.hintBottom, "rotating text should sit above the smart search bar").toBeLessThanOrEqual(
+ geometry!.pillTop + 1,
+ );
+ expect(geometry!.promptTop, "smart prompts should sit below the smart search bar").toBeGreaterThanOrEqual(
+ geometry!.pillBottom - 1,
);
- await suggestionRow.getByRole("button", { name: "lithium level timing" }).click();
+ await promptRow.getByRole("button", { name: "lithium level timing" }).click();
await expect(page.locator('[data-testid="global-search-input"]:visible').first()).toHaveValue(
"lithium level timing",
);
});
- test("phone smart search does not show the desktop suggested words row", async ({ page }) => {
+ test("phone smart search does not show the desktop rotating text or prompt row", async ({ page }) => {
await page.setViewportSize({ width: 390, height: 820 });
await mockDemoDashboard(page);
await gotoHome(page);
- await expect(page.getByTestId("smart-search-suggestion-row")).toBeHidden();
+ await expect(page.getByTestId("smart-search-rotating-text")).toBeHidden();
+ await expect(page.getByTestId("smart-search-prompt-row")).toBeHidden();
});
});