feat(ui): compact bottom search dock on phones everywhere except the home hero#964
Conversation
…home hero
On phones (<640px) every search surface now uses the compact single-row
bottom pill (the submitted-results dock style): standalone and dashboard
mode homes stop portaling the composer into the hero below sm and dock it
at the bottom edge instead, and the answer conversation dock drops to the
compact treatment whenever its follow-up chip row is absent. The home page
("How can I help?") is the only phone surface that keeps the in-flow hero
pill, and it is now also the only phone surface showing the APP-5
"Do not enter patient-identifiable information" notice; tablet/desktop
composers keep the notice everywhere as before.
- MasterSearchHeader: new heroComposerBreakpoint prop ("all" | "sm-up")
gates the hero portal media query and re-enables the phone dock for
sm-up hero hosts; phone privacy notice scoped to the home hero; answer
dock joins the compact styling when no follow-up row renders
- Hosts: GlobalSearchShell and ClinicalDashboard always pass the compact
dock variant, reserve dock clearance on phone mode homes, and keep the
answer home on the "all" hero breakpoint
- mobile-composer-reserve: dock reserves unified (shellDock/dashboardDock,
5.5rem/5rem + safe-area); answer reserves trimmed to the notice-free
dock, follow-up row reserve unchanged
- Hide-on-scroll, edge-to-edge scrim, safe-area handling, and the hidden
0.75rem pad are unchanged and covered by the updated Playwright specs
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SF3LtSFni9tbBCkBxGazkr
|
This pull request has been ignored for the connected project Preview Branches by Supabase. |
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (4)
💤 Files with no reviewable changes (1)
🚧 Files skipped from review as they are similar to previous changes (2)
📝 WalkthroughWalkthroughMobile composer behavior distinguishes phone docks from tablet/desktop hero composers. Reserve calculations, responsive header placement, page spacing, edge-to-edge styling, and UI tests are updated for answer and non-answer mode homes. ChangesMobile composer docking
Estimated code review effort: 3 (Moderate) | ~25 minutes Sequence Diagram(s)sequenceDiagram
participant ClinicalDashboard
participant GlobalStandaloneSearchShellClient
participant MobileComposerReserve
participant MasterSearchHeader
ClinicalDashboard->>MobileComposerReserve: resolve dashboard dock reserve
GlobalStandaloneSearchShellClient->>MobileComposerReserve: resolve shell dock reserve
ClinicalDashboard->>MasterSearchHeader: configure answer or mode-home breakpoint
GlobalStandaloneSearchShellClient->>MasterSearchHeader: configure sm-up hero and compact phone dock
MasterSearchHeader->>MasterSearchHeader: render hero composer or bottom dock
Possibly related PRs
Suggested labels: Suggested reviewers: 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Comment |
|
You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard. |
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (1)
src/components/clinical-dashboard/mobile-composer-reserve.ts (1)
23-30: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winDuplicate literal reserve values risk silent drift.
shellAnswer/shellDockshare the exact same string ("calc(5.5rem + var(--safe-area-bottom))"), anddashboardAnswer/dashboardDockshare"calc(5rem + var(--safe-area-bottom))". This is intentional today (per the comment, the answer dock without follow-ups is supposed to match the generic compact dock), butmaster-search-header.tsx'susesCompactMobileBottomStylerelies on this equality holding implicitly — nothing in code enforces it. If either pair diverges later (e.g. tuningdashboardDockfor a redesign but forgettingdashboardAnswer), the CSS-driven compact height and the JS-computed content reserve would silently disagree, causing overlap/gap bugs that are easy to miss in review.Consider deriving the "answer, no follow-ups" values from the dock constants instead of duplicating the literal:
♻️ Suggested refactor
+const shellCompactSingleRowReserve = "calc(5.5rem + var(--safe-area-bottom))"; +const dashboardCompactSingleRowReserve = "calc(5rem + var(--safe-area-bottom))"; + export const mobileComposerVisibleReserve = { - shellAnswer: "calc(5.5rem + var(--safe-area-bottom))", - shellDock: "calc(5.5rem + var(--safe-area-bottom))", + shellAnswer: shellCompactSingleRowReserve, + shellDock: shellCompactSingleRowReserve, dashboardAnswerWithFollowUps: "calc(7.5rem + var(--safe-area-bottom))", - dashboardAnswer: "calc(5rem + var(--safe-area-bottom))", - dashboardDock: "calc(5rem + var(--safe-area-bottom))", + dashboardAnswer: dashboardCompactSingleRowReserve, + dashboardDock: dashboardCompactSingleRowReserve, differentialsCompare: mobileComposerDifferentialsCompareReserve, } as const;🤖 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/mobile-composer-reserve.ts` around lines 23 - 30, Derive shellAnswer from shellDock and dashboardAnswer from dashboardDock within mobileComposerVisibleReserve instead of repeating their literal reserve strings. Preserve the existing equality between each answer/dock pair so usesCompactMobileBottomStyle and the computed content reserve cannot silently diverge.
🤖 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-tools.spec.ts`:
- Around line 1918-1919: Update the reserve assertion in the mobile composer
test to use a greater-than-or-equal comparison at 80px, allowing the documented
80px floor when the safe-area inset is zero.
---
Nitpick comments:
In `@src/components/clinical-dashboard/mobile-composer-reserve.ts`:
- Around line 23-30: Derive shellAnswer from shellDock and dashboardAnswer from
dashboardDock within mobileComposerVisibleReserve instead of repeating their
literal reserve strings. Preserve the existing equality between each answer/dock
pair so usesCompactMobileBottomStyle and the computed content reserve cannot
silently diverge.
🪄 Autofix (Beta)
❌ Autofix failed (check again to retry)
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: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro Plus
Run ID: 994f99cc-c113-4328-9595-5e490093c132
📒 Files selected for processing (8)
src/app/globals.csssrc/components/ClinicalDashboard.tsxsrc/components/clinical-dashboard/global-search-shell.tsxsrc/components/clinical-dashboard/master-search-header.tsxsrc/components/clinical-dashboard/mobile-composer-reserve.tstests/mobile-composer-reserve.test.tstests/ui-smoke.spec.tstests/ui-tools.spec.ts
|
Note Autofix is a beta feature. Expect some limitations and changes as we gather feedback and continue to improve it. The branch was updated while autofix was in progress. Please try again. |
… reserve assertions Address CodeRabbit review: share one constant per shell/dashboard compact reserve so the answer/dock pairs cannot silently diverge, and assert the dock reserve with >= so a zero safe-area inset landing exactly on the 5rem/5.5rem floor cannot flake the service-detail clearance spec. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01SF3LtSFni9tbBCkBxGazkr
|
Note Autofix is a beta feature. Expect some limitations and changes as we gather feedback and continue to improve it. Autofix skipped. No unresolved CodeRabbit review comments with fix instructions found. |
…bar-redesign-pxf7b3 # Conflicts: # tests/ui-tools.spec.ts
|
@coderabbitai please resolve the merge conflict here for me. |
|
✅ No merge conflicts detected when merging into Your branch is good to go! |
…pse-budget gate) (#993) * fix(ui): stop phone scroll locking to the bottom on mode homes (collapse-budget gate) Since #964 docked the compact composer on phone mode homes, one hide-on-scroll event releases ~180-260px of scroll geometry (72-130px header grid collapse + ~110px reserve-pad shrink, both animated). Mode-home content is short, so the release exceeds the remaining scroll runway: scrollTop clamps straight onto the new bottom edge, a 12px upward drag re-reveals and snaps the geometry back under the finger, and the hide/reveal loop reads as "scroll locks to the bottom" with a blank band below the content (reported on /formulation, iOS installed PWA; reproduced and quantified in Chromium: runway 266->84 on hide, 2 chrome flips in a single gesture). Fix: a collapse-budget gate in computeScrollHideUpdate. Hosts report how much layout the chrome would release if it hid right now (readChromeCollapseBudget: collapsible header strip + every dock-clearance pad above the shared 0.75rem hidden size - shell reserve pad, DocumentViewer content pad, scroller-padding fallback), and hiding is refused unless the remaining runway can absorb the release plus the reveal-intent distance and slack. Short pages keep their chrome and scroll plainly; long pages hide mid-scroll exactly as before but can no longer start a hide at the bottom edge. The existing one-sided bottom-clamp guard is untouched. Consumers that report no budget keep today's behavior. Also fixes a latent DocumentViewer bug the new sweep exposed: its one-shot #main-content lookup could permanently hold a detached node when the shell remounts the scroller, silently killing the viewer's hide-on-scroll. The discovery observer now stays alive for the viewer's lifetime (childList-only, deduped setState). Guardrails: - tests/ui-phone-scroll.spec.ts: 18-test sweep over all 10 standalone mode homes, the 3 dashboard modes, and 4 long routes at phone viewports with reducedMotion "no-preference" (the suite-wide "reduce" default disables the very transitions that caused this bug - that is how #964 shipped green) and simulated PWA safe-area insets. Asserts sole-scrollport, no horizontal overflow, true-bottom reachability, and bottom-edge nudge stability (at most one chrome flip). Verified to fail red against the pre-fix behavior. - tests/use-hide-on-scroll.test.ts: oscillation reproduction harness plus runway-refusal, ample-runway, boundary, and budget-omitted back-compat cases. - ui-smoke: bottom-hide scenario updated to the gate contract (hide with runway remaining, then ride the geometry clamp to the bottom while hidden). Verified: vitest focused suites, ui-phone-scroll + ui-formulation + ui-tools + ui-smoke (chromium), webkit advisory sweep, verify:cheap, verify:ui (264 passed), verify:pr-local. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * docs: record claude/phone-scroll-fix review in branch ledger Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * fix(ui): clear shell scroll container on remount; fail flip counter loudly Addresses two CodeRabbit findings on #993: - DocumentViewer kept a detached #main-content node across a two-step shell remount, leaving useHideOnScroll subscribed to a scroller that never fires. Syncing null lets it fall back to window. - installFlipCounter returned early when the header selector missed, pinning the counter at 0 so flip assertions passed vacuously. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix(ci): overlay-aware flip counter + restore DocumentViewer line budget The answer home hides its glass header via the overlay strategy (header#search carries data-scroll-hidden; no collapse wrapper exists), so the fail-loudly flip counter must observe whichever chrome element the route renders. Condense the DocumentViewer discovery comments back under the 3166-line no-growth maintainability budget while keeping the remount rationale. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> --------- Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Summary
/services,/forms,/differentials,/dsm,/specifiers,/formulation,/factsheets,/therapy-compass,/tools,/favourites,/?mode=…) stop portaling the composer into the hero belowsmand dock it at the bottom edge instead; the answer conversation dock joins the compact treatment whenever its follow-up chip row is absent./answer home, "How can I help?") is the only phone surface that keeps the in-flow hero pill, and it is now also the only phone surface showing the APP-5 "Do not enter patient-identifiable information" notice. Tablet/desktop composers are unchanged (hero fromsmup, notice everywhere).MasterSearchHeadergains aheroComposerBreakpointprop ("all" | "sm-up") gating the hero-portal media query; sm-up hero hosts re-enable the phone bottom dock. Hide-on-scroll, the edge-to-edge blur scrim, safe-area handling, and the 0.75rem hidden pad are unchanged.mobile-composer-reservedock reserves unified (shellDock/dashboardDock, 5.5rem/5rem + safe-area); answer-dock reserves trimmed to the notice-free pill; the follow-up-row reserve (7.5rem) and differentials Compare reserve are unchanged.Verification
npm run verify:pr-local— format, runtime, unit suite (2973 passed; 1 pre-existing container-only failure intests/pdf-extraction-budget.test.tsreproduced identically on the unmodified base — Python child-tree termination, unrelated to this diff), plusnpm run build+ client-bundle secret scan run directly and passingnpm run verify:cheap— same single pre-existing failure, all other checks passnpm run verify:uispec set for the touched surfaces):ui-tools84/84,ui-smoke+ui-accessibility+ui-overlap+ui-universal-search130 passed with only the pre-existing PDF-canvas container failure (also reproduced on unmodified base),ui-formulation+ui-specifiers+ui-route-coverage23/23. The full multi-browserverify:uirun was executed only for Chromium: this container lacks the pinned Playwright headless shell, so specs ran against/opt/pw-browsers/chromiumviaPLAYWRIGHT_CHROMIUM_EXECUTABLE_PATH.npm run check:production-readiness— passes except expected missing-secret failures in this demo-mode container (no Supabase/OpenAI keys), per repo cloud notesRisk and rollout
Clinical Governance Preflight
Clinical KB Database(sjrfecxgysukkwxsowpy)Notes
/privacy. Flagged here for governance awareness since phone deep links to non-home surfaces no longer show the inline notice.data-footer-variant="compact"attribute now applies to every phone dock (including the answer dock without follow-ups), so the compact scrim/padding CSS is shared rather than duplicated.🤖 Generated with Claude Code
https://claude.ai/code/session_01SF3LtSFni9tbBCkBxGazkr
Summary by CodeRabbit