Skip to content

fix(mobile): keep home-page search in the hero and drop the phone command popup#473

Merged
BigSimmo merged 13 commits into
mainfrom
claude/mobile-search-bar-popup-bx163m
Jul 11, 2026
Merged

fix(mobile): keep home-page search in the hero and drop the phone command popup#473
BigSimmo merged 13 commits into
mainfrom
claude/mobile-search-bar-popup-bx163m

Conversation

@BigSimmo

@BigSimmo BigSimmo commented Jul 10, 2026

Copy link
Copy Markdown
Owner

Summary

  • On phones, mode-home pages docked the shared search composer to the bottom edge and opened the universal command popup above it, crowding the small screen (see reported screenshot). The hero-slot portal was gated to (min-width: 640px), so phones never got the in-flow hero placement tablet+ already had — even though docs/codebase-index.md documents mode homes as hero-placed "on phone and tablet+ alike".
  • Portal the composer into the mode-home hero slot at every viewport width, so phone home pages (/, /?mode=documents|prescribing|tools, /services, /forms, /favourites, /differentials, /applications) show the search pill mid-screen under the hero. Result and answer-thread views keep the bottom dock.
  • Remove the universal command popup on phones: the dropdown is hidden below sm for bottom-docked composers (inline placement already hid it below lg), its typeahead fetches are skipped at widths where nothing can display them, and the phone dock scrim no longer expands for a popup that never shows.
  • Guard the shared composer input ref across hero/dock transitions: both composers briefly coexist while navigating home → results, and React nulled the plain shared queryInputRef when the outgoing portal composer unmounted, silently breaking focus helpers (quote follow-up draft focus, / shortcut). The input now binds through a cleanup-function ref that only clears the binding it still owns.
  • Remove the now-redundant heroComposerFromTablet prop and drop the phone bottom-dock clearance paddings on home views that no longer have a dock (dashboard hubs, tools launcher, standalone shell reserve).
  • Playwright: replaced the phone "popup opens above the pill" test with "popup stays hidden on phones", and added a phone mode-home test asserting the composer renders in the hero (in-flow, not the fixed dock) across /services, /forms, /differentials, /applications.

Verification

  • npm run verify:pr-local

During development, use npm run verify:cheap as the faster iteration gate before the final PR-local preflight.

  • npm run verify:cheap — lint, typecheck, 1438 vitest tests pass
  • npm run verify:ui equivalent (Chromium, full spec set): ui-smoke 59/59, ui-tools 41/41, ui-overlap 12/12, ui-universal-search 5/5, ui-accessibility + ui-stress + ui-tools-collapse + ui-tools-task-directory all pass. The one initial ui-smoke failure (quote follow-up focus) was a real regression from the hero/dock transition and is fixed by the guarded ref commit; suite confirmed green on re-run.
  • Manual phone-width (390×844) screenshots of all mode homes: composer sits under the hero mid-screen, typing shows no popup; submitted-search views keep the bottom dock with no popup
  • npm run verify:release before release or handoff confidence claims
  • npm run eval:retrieval:quality — not needed: no retrieval, ranking, selection, chunking, or scoring behavior changed
  • npm run eval:rag — not needed: no answer generation changes
  • npm run check:production-readiness — not needed: no clinical workflow, privacy, env, Supabase, or governance behavior changed

Clinical Governance Preflight

Not applicable: this change is composer placement + popup visibility CSS/portal behavior only. It does not touch ingestion, answer generation, search/ranking logic, source rendering, document access, privacy, production env, or clinical output.

Notes

  • The universal-search typeahead endpoint is no longer queried while typing on phones (the popup that consumed the results cannot render there), which also removes wasted per-keystroke fetches on mobile.

🤖 Generated with Claude Code

https://claude.ai/code/session_013mCpzKWTCtBSLC6p1NsSWo

…mand popup

On phones, mode-home pages docked the shared search composer to the bottom
edge and opened the universal command popup above it, crowding the small
screen. The hero-slot portal was gated to (min-width: 640px), so phones never
used the in-flow hero placement that tablet+ already had.

- Portal the composer into the mode-home hero slot at every viewport width,
  so phone home pages show the search pill mid-screen under the hero instead
  of a fixed bottom dock. Result and answer-thread views keep the dock.
- Hide the universal command dropdown below sm for bottom-docked composers
  (inline placement already hid it below lg), skip its typeahead fetches at
  widths where nothing can display them, and stop the phone dock scrim from
  expanding for a popup that never shows.
- Remove the now-redundant heroComposerFromTablet prop and the phone
  bottom-dock clearance paddings on home views that no longer have a dock.
- Update the phone Playwright coverage: the popup must stay hidden on phones
  and mode homes must render the composer in the hero, not the bottom dock.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013mCpzKWTCtBSLC6p1NsSWo
@supabase

supabase Bot commented Jul 10, 2026

Copy link
Copy Markdown

This pull request has been ignored for the connected project sjrfecxgysukkwxsowpy because there are no changes detected in supabase directory. You can change this behaviour in Project Integrations Settings ↗︎.


Preview Branches by Supabase.
Learn more about Supabase Branching ↗︎.

@coderabbitai

coderabbitai Bot commented Jul 10, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Responsive search composer routing, ref handling, viewport-aware command visibility, safe-area spacing, and phone UI coverage were updated. Desktop-home slots now control composer placement, while phone command interactions remain hidden when the surface is not displayable.

Changes

Responsive search composer behavior

Layer / File(s) Summary
Home composer portal and shared input routing
src/components/clinical-dashboard/master-search-header.tsx, src/components/clinical-dashboard/global-mockup-search-shell.tsx, src/components/ClinicalDashboard.tsx
Home composer slots, fallback rendering, phone dock activation, shared input ref binding, and composer state handling were updated.
Viewport-aware command surface visibility
src/components/clinical-dashboard/universal-search-command-surface.tsx
Command dropdown rendering, keyboard handling, focus behavior, and universal search fetching now respect breakpoint visibility.
Mobile composer spacing and safe-area layout
src/components/clinical-dashboard/global-mockup-search-shell.tsx, src/components/ClinicalDashboard.tsx, src/components/applications-launcher-page.tsx
Mobile reserve, content clearance, and bottom padding now account for composer state and safe-area insets.
Phone search placement coverage
tests/ui-tools.spec.ts, tests/ui-smoke.spec.ts, docs/branch-review-ledger.md
Phone tests verify hidden command popups, hero composer placement, absent docks, route behavior, and viewport overflow constraints; the review ledger records the review entry.

Estimated code review effort: 4 (Complex) | ~45 minutes

Sequence Diagram(s)

sequenceDiagram
  participant PhoneUser
  participant MasterSearchHeader
  participant UniversalSearchCommandSurface
  participant SharedQueryInput
  PhoneUser->>MasterSearchHeader: focus search composer
  MasterSearchHeader->>SharedQueryInput: bind and focus active input
  MasterSearchHeader->>UniversalSearchCommandSurface: provide composer interaction state
  UniversalSearchCommandSurface->>UniversalSearchCommandSurface: evaluate placement breakpoint
  UniversalSearchCommandSurface-->>PhoneUser: keep dropdown and fetching disabled when unavailable
Loading
🚥 Pre-merge checks | ✅ 10 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 70.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (10 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly describes the main mobile search change: keeping home search in the hero and removing the phone command popup.
Description check ✅ Passed The description follows the repository template with Summary, Verification, and Clinical Governance Preflight sections and covers the changed behavior well.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Generated And Sensitive Files ✅ Passed Merge-base diff shows only 8 text files under src/tests/docs; no secrets, .env files, logs, caches, binaries, or generated artifacts.
Verification Claims ✅ Passed Verification notes name exact commands/results (npm run verify:cheap, verify:ui, git diff --check), and unchecked items are clearly marked not run.
Risky Git Or Deployment Actions ✅ Passed PASS: The PR only changes search UI/tests/docs, and no changed file instructs force-push, reset --hard, destructive clean, branch deletion, or deployment without confirmation.
Supabase Project And Schema Safety ✅ Passed PR diff only touches UI/tests/docs; no Supabase env, schema, migration, or RLS/policy files changed, and existing project guards still target the expected ref.
Runtime And Package Manager Integrity ✅ Passed No package-manager, lockfile, or engine/runtime files changed; repo still pins npm@11.17.0, Node 24.x, and engine-strict=true.
Api Route Failure Handling ✅ Passed PR only changes client-side composer/search UI; no API route, server action, RAG, ingestion, or provider code was added or modified, so no new failure-handling gap appears.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch claude/mobile-search-bar-popup-bx163m
✨ Simplify code
  • Create PR with simplified code
  • Commit simplified code in branch claude/mobile-search-bar-popup-bx163m

Comment @coderabbitai help to get the list of available commands.

With the hero composer now active on phones, navigating from a mode home
into a result view briefly renders both composers; React nulls a plain
shared queryInputRef when the outgoing portal composer unmounts after the
dock composer has already bound it, so focus helpers (quote follow-up,
"/" shortcut) silently no-oped. Bind the input through a cleanup-function
ref that only clears the binding it still owns, and narrow the prop to the
RefObject shape every caller already passes.

Caught by ui-smoke "quote follow-up stages a composer draft from evidence
quotes"; full ui-smoke suite now passes (59/59).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013mCpzKWTCtBSLC6p1NsSWo
@BigSimmo
BigSimmo marked this pull request as ready for review July 11, 2026 07:51
@BigSimmo

Copy link
Copy Markdown
Owner Author

@copilot resolve the merge conflicts on this branch.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: a30d170434

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/components/clinical-dashboard/global-mockup-search-shell.tsx (1)

258-282: 🎯 Functional Correctness | 🔴 Critical | ⚡ Quick win

Resolve the mobileComposerReserve conflict.

This unresolved conflict leaves the standalone search shell syntactically invalid. Keep one finalized reserve policy that matches the selected hero-versus-floating-composer layout.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/components/clinical-dashboard/global-mockup-search-shell.tsx` around
lines 258 - 282, Resolve the conflict in the mobileComposerReserve policy within
the global mockup search shell, removing all conflict markers and retaining only
one valid implementation. Align the reserve value with the selected
hero-versus-floating-composer layout, preserving inline standalone hero behavior
while reserving the fixed bottom composer only when it is actually rendered.

Source: Linters/SAST tools

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/components/applications-launcher-page.tsx`:
- Around line 736-741: Resolve the merge conflict in the applications launcher
JSX by removing the conflict markers and retaining the intended padding class
declaration, including its responsive safe-area behavior. Ensure the surrounding
component remains valid TypeScript/JSX and compiles successfully.

In `@src/components/clinical-dashboard/master-search-header.tsx`:
- Around line 73-81: Resolve all remaining merge conflicts in the
MasterSearchHeader module by removing every conflict marker and retaining the
mode-home hero behavior across all viewport widths. Preserve
desktopHomeComposerMediaQuery for desktop behavior and
modeHomeComposerMediaQuery as an always-matching query, and apply the same
consistent resolution at the additional conflict locations.

In `@src/components/clinical-dashboard/universal-search-command-surface.tsx`:
- Around line 317-332: Update the universal search interaction flow around
dropdownDisplayable and the component’s focus/keyboard handlers so ineligible
phone widths cannot open, navigate, or select hidden suggestions. Gate focus
handling, ArrowDown/Enter behavior, and dropdown rendering on
dropdownDisplayable, and when it becomes false close the dropdown and reset
related active/selection state so the combobox no longer reports expanded.

---

Outside diff comments:
In `@src/components/clinical-dashboard/global-mockup-search-shell.tsx`:
- Around line 258-282: Resolve the conflict in the mobileComposerReserve policy
within the global mockup search shell, removing all conflict markers and
retaining only one valid implementation. Align the reserve value with the
selected hero-versus-floating-composer layout, preserving inline standalone hero
behavior while reserving the fixed bottom composer only when it is actually
rendered.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: d73c8358-af02-4eeb-894f-6ac67f564431

📥 Commits

Reviewing files that changed from the base of the PR and between 54bd94d and fd4ce7e.

📒 Files selected for processing (6)
  • src/components/ClinicalDashboard.tsx
  • src/components/applications-launcher-page.tsx
  • src/components/clinical-dashboard/global-mockup-search-shell.tsx
  • src/components/clinical-dashboard/master-search-header.tsx
  • src/components/clinical-dashboard/universal-search-command-surface.tsx
  • tests/ui-tools.spec.ts

Comment thread src/components/applications-launcher-page.tsx Outdated
Comment thread src/components/clinical-dashboard/master-search-header.tsx Outdated
coderabbitai[bot]
coderabbitai Bot previously approved these changes Jul 11, 2026
BigSimmo added 4 commits July 11, 2026 16:49
# Conflicts:
#	docs/branch-review-ledger.md
# Conflicts:
#	docs/branch-review-ledger.md
#	src/components/clinical-dashboard/global-mockup-search-shell.tsx
#	tests/ui-tools.spec.ts

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 53ea5729b2

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

coderabbitai[bot]
coderabbitai Bot previously requested changes Jul 11, 2026

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
tests/ui-smoke.spec.ts (1)

1909-1911: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Use an exact match for the singular status

toContainText("1 source") still passes on 1 sources, so this check can miss a pluralization regression. Switch both assertions to an exact text target.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tests/ui-smoke.spec.ts` around lines 1909 - 1911, Update both sourceStatus
assertions to use an exact text match for “1 source” rather than substring
matching, ensuring the singular status does not pass when the UI displays “1
sources”.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@tests/ui-smoke.spec.ts`:
- Around line 210-214: Update the hostname allowlist in the request filtering
logic to include the bracketed IPv6 loopback value "[::1]" alongside the
existing loopback entries, so local IPv6 requests remain allowed.

---

Outside diff comments:
In `@tests/ui-smoke.spec.ts`:
- Around line 1909-1911: Update both sourceStatus assertions to use an exact
text match for “1 source” rather than substring matching, ensuring the singular
status does not pass when the UI displays “1 sources”.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 722b3082-3217-431b-87f9-7638c0fc8972

📥 Commits

Reviewing files that changed from the base of the PR and between c6d0f37 and 53ea572.

📒 Files selected for processing (5)
  • docs/branch-review-ledger.md
  • src/components/ClinicalDashboard.tsx
  • src/components/clinical-dashboard/global-mockup-search-shell.tsx
  • tests/ui-smoke.spec.ts
  • tests/ui-tools.spec.ts
✅ Files skipped from review due to trivial changes (1)
  • docs/branch-review-ledger.md
🚧 Files skipped from review as they are similar to previous changes (3)
  • src/components/ClinicalDashboard.tsx
  • tests/ui-tools.spec.ts
  • src/components/clinical-dashboard/global-mockup-search-shell.tsx

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Inline review comments failed to post. This is likely due to GitHub's internal server error or limits when posting large numbers of comments. If you are seeing this consistently it is likely a permissions issue. Please check "Moderation" -> "Code review limits" under your organization settings.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
tests/ui-smoke.spec.ts (1)

1909-1911: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Use an exact match for the singular status

toContainText("1 source") still passes on 1 sources, so this check can miss a pluralization regression. Switch both assertions to an exact text target.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tests/ui-smoke.spec.ts` around lines 1909 - 1911, Update both sourceStatus
assertions to use an exact text match for “1 source” rather than substring
matching, ensuring the singular status does not pass when the UI displays “1
sources”.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@tests/ui-smoke.spec.ts`:
- Around line 210-214: Update the hostname allowlist in the request filtering
logic to include the bracketed IPv6 loopback value "[::1]" alongside the
existing loopback entries, so local IPv6 requests remain allowed.

---

Outside diff comments:
In `@tests/ui-smoke.spec.ts`:
- Around line 1909-1911: Update both sourceStatus assertions to use an exact
text match for “1 source” rather than substring matching, ensuring the singular
status does not pass when the UI displays “1 sources”.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 722b3082-3217-431b-87f9-7638c0fc8972

📥 Commits

Reviewing files that changed from the base of the PR and between c6d0f37 and 53ea572.

📒 Files selected for processing (5)
  • docs/branch-review-ledger.md
  • src/components/ClinicalDashboard.tsx
  • src/components/clinical-dashboard/global-mockup-search-shell.tsx
  • tests/ui-smoke.spec.ts
  • tests/ui-tools.spec.ts
✅ Files skipped from review due to trivial changes (1)
  • docs/branch-review-ledger.md
🚧 Files skipped from review as they are similar to previous changes (3)
  • src/components/ClinicalDashboard.tsx
  • tests/ui-tools.spec.ts
  • src/components/clinical-dashboard/global-mockup-search-shell.tsx
🛑 Comments failed to post (1)
tests/ui-smoke.spec.ts (1)

210-214: 🩺 Stability & Availability | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/usr/bin/env bash
set -euo pipefail

node <<'NODE'
const hostname = new URL("http://[::1]:4173").hostname;
if (hostname !== "[::1]") {
  throw new Error(`Unexpected hostname serialization: ${hostname}`);
}
console.log(hostname);
NODE

Repository: BigSimmo/Database

Length of output: 161


🏁 Script executed:

#!/usr/bin/env bash
set -euo pipefail

python3 - <<'PY'
from pathlib import Path
p = Path("tests/ui-smoke.spec.ts")
text = p.read_text()
for i, line in enumerate(text.splitlines(), 1):
    if 180 <= i <= 240:
        print(f"{i:4d}: {line}")
PY

Repository: BigSimmo/Database

Length of output: 2458


Allow bracketed IPv6 loopback in the allowlist.
URL.hostname returns "[::1]" for IPv6 loopback, so the current "::1" entry never matches and local IPv6 app requests get blocked as external.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tests/ui-smoke.spec.ts` around lines 210 - 214, Update the hostname allowlist
in the request filtering logic to include the bracketed IPv6 loopback value
"[::1]" alongside the existing loopback entries, so local IPv6 requests remain
allowed.

coderabbitai[bot]
coderabbitai Bot previously approved these changes Jul 11, 2026
@BigSimmo
BigSimmo dismissed coderabbitai[bot]’s stale review July 11, 2026 10:52

Findings fixed in ceccc72: exact singular source assertion and bracketed IPv6 loopback allowlist.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants