Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions src/app/globals.css
Original file line numberDiff line numberDiff line change
Expand Up@@ -1236,6 +1236,16 @@ summary::-webkit-details-marker {
min-width: 0;
}

.smart-search-suggestion-row {
display: none;
}

@media (min-width: 1024px) {
.smart-search-suggestion-row {
display: flex;
}
}

.answer-suggestion-label {
color: var(--text-soft);
font-size: 0.6875rem;
Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -8,6 +8,7 @@ import {
type ModeActionId,
type ModeActionSetId,
} from "@/components/clinical-dashboard/mode-action-popup";
import { AnswerSuggestionChips } from "@/components/clinical-dashboard/answer-suggestion-chips";
import { cn } from "@/components/ui-primitives";
import { appModeDefinition, type AppModeId } from "@/lib/app-modes";
import { appModeIcons } from "@/lib/app-mode-icons";
Expand DownExpand Up@@ -53,6 +54,19 @@ 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 }) {
return (
<AnswerSuggestionChips
suggestions={examples}
onPick={onPickExample}
label="Suggested"
testId="smart-search-suggestion-row"
layout="scroll"
className="smart-search-suggestion-row"
/>
);
}

function ScopeChipRow({
scopes,
activeScopes,
Expand DownExpand Up@@ -531,6 +545,14 @@ export function UniversalSearchCommandSurface({
placement === "bottom-dock" ? "gap-1" : "gap-2",
)}
>
<ContextHintRow
examples={config.examples}
onPickExample={(example) => {
onQueryChange(example);
onDropdownOpenChange(true);
onFocusSearchInput?.();
}}
/>
<div
className="relative w-full"
onKeyDownCapture={(event) => {
Expand Down
38 changes: 38 additions & 0 deletions tests/ui-overlap.spec.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -153,4 +153,42 @@ test.describe("Header element overlap coverage", () => {
).toBeLessThanOrEqual(geometry!.clearLeft + 1);
});
}

test("desktop smart search keeps suggested words above 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 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 };
});

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,
);

await suggestionRow.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 }) => {
await page.setViewportSize({ width: 390, height: 820 });
await mockDemoDashboard(page);
await gotoHome(page);

await expect(page.getByTestId("smart-search-suggestion-row")).toBeHidden();
});
});
Loading