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 number Diff line number Diff line change
Expand Up @@ -1091,6 +1091,16 @@ summary::-webkit-details-marker {
transform: translateX(-50%);
}

/* Compact search/result views: no chip row below the pill, so the pill
itself hugs the bottom edge and the scrim shrinks to match. */
.document-mobile-search-edge.answer-footer-search-edge.document-mobile-search-compact {
bottom: max(0.4rem, calc(var(--safe-area-bottom) + 0.3rem));
}

.document-mobile-search-compact .answer-footer-search-backdrop {
height: max(5rem, calc(var(--safe-area-bottom) + 4.4rem));
}

.document-mobile-search-pill {
min-height: 3.6rem;
border-color: var(--border-strong);
Expand Down
13 changes: 11 additions & 2 deletions src/components/ClinicalDashboard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5373,6 +5373,10 @@ export function ClinicalDashboard({
// stay top-aligned so their lists start in a stable position.
const centeredModeHome =
showDesktopHomeComposer && activeModeResultKind !== "tools" && activeModeResultKind !== "favourites";
// Submitted (non-answer) searches are result views, not mode homes: on phones
// the bottom composer drops its chip row and hugs the screen edge so results
// keep maximum vertical space. Mode homes keep the default chip-row layout.
const compactMobileBottomSearch = hasMobileBottomSearch && modeSearchSubmitted;
const renderDegradedNotice = () => (
<UtilityDrawer
icon={!isOnline ? WifiOff : AlertCircle}
Expand Down Expand Up @@ -5544,6 +5548,7 @@ export function ClinicalDashboard({
queryInputRef={composerInputRef}
queryInputAutoFocus={focusSearch}
mobileSearchPlacement={hasMobileBottomSearch ? "bottom" : "default"}
mobileBottomSearchVariant={compactMobileBottomSearch ? "compact" : "default"}
desktopHomeComposerSlotId={desktopHomeComposerSlotId}
heroComposerFromTablet={Boolean(desktopHomeComposerSlotId)}
/>
Expand All @@ -5558,7 +5563,9 @@ export function ClinicalDashboard({
searchMode === "answer"
? "mb-[calc(5.25rem+env(safe-area-inset-bottom))] sm:mb-24"
: hasMobileBottomSearch
? "mb-[calc(5.25rem+env(safe-area-inset-bottom))] sm:mb-0"
? compactMobileBottomSearch
? "mb-[calc(4.5rem+env(safe-area-inset-bottom))] sm:mb-0"
: "mb-[calc(5.25rem+env(safe-area-inset-bottom))] sm:mb-0"
: "mb-0",
)}
>
Expand All @@ -5569,7 +5576,9 @@ export function ClinicalDashboard({
searchMode === "answer"
? "pb-32 sm:pb-36 lg:pb-40"
: hasMobileBottomSearch
? "pb-32 sm:pb-10 lg:pb-12"
? compactMobileBottomSearch
? "pb-8 sm:pb-10 lg:pb-12"
: "pb-32 sm:pb-10 lg:pb-12"
: "pb-8 sm:pb-10 lg:pb-12",
)}
>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -363,6 +363,10 @@ function GlobalMockupSearchShellClient({
queryInputRef={inputRef}
headerVariant={isDifferentialPresentationWorkflow ? "workflow" : "default"}
mobileSearchPlacement="bottom"
// Submitted searches that stay in the shell (services results) are
// result views: compact the phone bottom composer so results keep
// maximum screen space. Mode homes keep the chip-row layout.
mobileBottomSearchVariant={hasSubmittedModeSearch ? "compact" : "default"}
desktopSearchPlacement={
(desktopSearchPlacement === "hero" || isFormsOnlyShell) && isStandaloneModeHome ? "hero" : "default"
}
Expand All @@ -381,7 +385,9 @@ function GlobalMockupSearchShellClient({
? "pb-8"
: searchMode === "answer"
? "pb-[calc(9rem+env(safe-area-inset-bottom))]"
: "pb-[calc(9rem+env(safe-area-inset-bottom))] sm:pb-8",
: hasSubmittedModeSearch
? "pb-[calc(5.5rem+env(safe-area-inset-bottom))] sm:pb-8"
: "pb-[calc(9rem+env(safe-area-inset-bottom))] sm:pb-8",
)}
>
{children}
Expand Down
12 changes: 11 additions & 1 deletion src/components/clinical-dashboard/master-search-header.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -202,6 +202,7 @@ export function MasterSearchHeader({
queryInputAutoFocus = false,
headerVariant = "default",
mobileSearchPlacement = "default",
mobileBottomSearchVariant = "default",
desktopSearchPlacement = "default",
searchComposerVisible = true,
desktopHomeComposerSlotId,
Expand Down Expand Up @@ -239,6 +240,10 @@ export function MasterSearchHeader({
queryInputAutoFocus?: boolean;
headerVariant?: "default" | "workflow";
mobileSearchPlacement?: "default" | "bottom";
/** "compact" drops the phone footer chip row and hugs the bottom edge —
* used by search/result views so results keep maximum screen space.
* Mode homes keep the default chip-row layout. */
mobileBottomSearchVariant?: "default" | "compact";
desktopSearchPlacement?: "default" | "hero";
searchComposerVisible?: boolean;
desktopHomeComposerSlotId?: string;
Expand Down Expand Up @@ -1127,9 +1132,13 @@ export function MasterSearchHeader({
const isDesktopHomeComposer = placement === "desktop-home";
const usesAnswerFooterStyle = isAnswerFooterComposer && !isDesktopHomeComposer;
const usesMobileBottomStyle = isMobileBottomComposer && !isDesktopHomeComposer;
const usesCompactMobileBottomStyle = usesMobileBottomStyle && mobileBottomSearchVariant === "compact";
const usesBottomComposerPlacement = usesAnswerFooterStyle || (usesMobileBottomStyle && usesPhoneSearchLayout);
const usesFooterChipLayout = usesBottomComposerPlacement || isDesktopHomeComposer;
const showFooterSearchChips = usesFooterChipLayout;
// Compact search views drop the chip row on phones so the pill can sit
// flush with the bottom edge; the same actions stay reachable via the
// integrated "+" menu.
const showFooterSearchChips = usesFooterChipLayout && !usesCompactMobileBottomStyle;
// The visible footer/hero composer chrome is universal; submit semantics still
// come from the active mode.
const usesSendAffordance = searchMode === "answer" || usesFooterChipLayout;
Expand Down Expand Up @@ -1166,6 +1175,7 @@ export function MasterSearchHeader({
)
: "universal-top-search-edge sticky top-[calc(4.75rem+env(safe-area-inset-top))] z-20 mx-auto box-border w-full px-3 py-3 sm:px-4",
usesBottomComposerPlacement && "answer-footer-search-edge",
usesCompactMobileBottomStyle && "document-mobile-search-compact",
usesFooterChipLayout && "flex flex-col items-center gap-2.5",
)}
>
Expand Down
21 changes: 17 additions & 4 deletions tests/ui-tools.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -283,6 +283,8 @@ test.describe("Clinical KB applications launcher", () => {
expect(metrics?.position).toBe("fixed");
expect(metrics?.formWidth ?? 0).toBeLessThanOrEqual(390 - 8);
expect(metrics?.pillClassName).toContain("answer-footer-search-pill");
// Mode homes keep the footer chip row under the pill on phones.
await expect(page.locator(".answer-footer-search-chip:visible").first()).toBeVisible();
await expectNoPageHorizontalOverflow(page);
}
});
Expand Down Expand Up @@ -343,21 +345,32 @@ test.describe("Clinical KB applications launcher", () => {
] as const) {
await page.setViewportSize({ width: viewport.width, height: viewport.height });

for (const route of ["/services?q=13YARN&focus=1&run=1", "/services/13yarn"] as const) {
await gotoLauncher(page, route);
for (const route of [
{ path: "/services?q=13YARN&focus=1&run=1", compactBottomSearch: true },
{ path: "/services/13yarn", compactBottomSearch: false },
] as const) {
await gotoLauncher(page, route.path);
await expect(page.getByRole("button", { name: "Mode Services" })).toBeVisible({ timeout: 20_000 });
await expect(visibleGlobalSearchInput(page), `${route} at ${viewport.name}`).toHaveCount(1, {
await expect(visibleGlobalSearchInput(page), `${route.path} at ${viewport.name}`).toHaveCount(1, {
timeout: 20_000,
});

const metrics = await globalSearchComposerMetrics(page);
expect(metrics, `${route} at ${viewport.name}`).not.toBeNull();
expect(metrics, `${route.path} at ${viewport.name}`).not.toBeNull();
expect(metrics?.pillClassName).toContain("answer-footer-search-pill");
expect(metrics?.formWidth ?? 0).toBeLessThanOrEqual(viewport.width - 8);

if (viewport.width < 640) {
expect(metrics?.position).toBe("fixed");
expect(metrics?.formCenterY ?? 0).toBeGreaterThan(viewport.height * 0.72);
if (route.compactBottomSearch) {
// Search result views drop the chip row and hug the bottom edge
// on phones so results keep maximum screen space.
await expect(page.locator(".answer-footer-search-chip:visible")).toHaveCount(0);
expect(metrics?.formBottom ?? 0).toBeGreaterThanOrEqual(viewport.height - 48);
} else {
await expect(page.locator(".answer-footer-search-chip:visible").first()).toBeVisible();
}
} else {
expect(metrics?.position).toBe("sticky");
expect(metrics?.formCenterY ?? viewport.height).toBeLessThan(viewport.height * 0.25);
Expand Down