Skip to content

fix(chrome): keep tablet/desktop search page-anchored outside sticky header#1239

Closed
BigSimmo wants to merge 6 commits into
mainfrom
cursor/page-anchored-search-composer-30ee
Closed

fix(chrome): keep tablet/desktop search page-anchored outside sticky header#1239
BigSimmo wants to merge 6 commits into
mainfrom
cursor/page-anchored-search-composer-30ee

Conversation

@BigSimmo

@BigSimmo BigSimmo commented Jul 25, 2026

Copy link
Copy Markdown
Owner

Summary

On tablet/desktop results pages (e.g. /services?q=…), the search pill was glued under the sticky top bar. That was a regression from PR #1222: the sticky collapse wrapper wrapped header + composer, so hide-on-scroll chrome pulled the search into the header strip.

Root cause: MasterSearchHeader put headerAndComposer inside [data-testid="universal-header-collapse"] with sm:sticky. Combined with the composer’s own sm:sticky top-[4.75rem], the search behaved as header chrome instead of page content.

Fix:

  • Only header#search (mode / new chat / etc.) lives in the sticky collapse wrapper
  • Tablet/desktop results composers render outside that wrapper as sm:static / relative (page-anchored)
  • Phone bottom dock, answer footer, and hero-portaled composers unchanged
  • Docs + static contract + Playwright regression for /services results

Verification

  • npx vitest run tests/header-scroll-hide-contract.test.ts (11 passed)
  • npm run verify:cheap (3462 tests passed)
  • npm run test:e2e -- tests/ui-chrome-scroll.spec.ts --project=chromium (14 passed, including new services page-anchored cases)
  • Manual browser check at desktop 1440 and tablet 834 on /services?q=services&focus=1&run=1 — search scrolls away; not stuck under header

Risk and rollout

  • Risk: Low — UI chrome ownership only
  • Rollback: Revert this PR
  • Provider or production effects: None

Notes

No RAG / clinical / schema impact.

Open in Web Open in Cursor 

Summary by CodeRabbit

  • Bug Fixes
    • Improved search composer behavior on tablet and desktop screens.
    • Search composers now remain anchored within page content and scroll naturally, rather than sticking beneath the header.
    • Refined header hide and reveal behavior so the top bar and search composer respond consistently during scrolling.
    • Added safeguards to preserve correct placement across hero and search-results views.

…header

PR #1222 wrapped header+composer in the sticky collapse wrapper, so results
search stuck under the top bar on sm+. Only the mode/new-chat bar stays sticky;
the composer scrolls with the page.

Co-authored-by: BigSimmo <BigSimmo@users.noreply.github.com>
@supabase

supabase Bot commented Jul 25, 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 25, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

Tablet/desktop search composers now remain page-anchored in normal document flow, while only the top-bar chrome participates in sticky collapse behavior. Documentation, component comments, static contracts, and breakpoint UI tests were updated accordingly.

Changes

Search composer placement

Layer / File(s) Summary
Placement contract and documentation
docs/search-chrome-behaviour.md, src/components/clinical-dashboard/global-search-shell.tsx, src/components/clinical-dashboard/master-search-header.tsx
Documentation and comments describe tablet/desktop composers as in-flow and outside sticky header chrome.
Composer rendering and collapse scoping
src/components/clinical-dashboard/master-search-header.tsx
Tablet/desktop positioning uses static layout, and the collapse wrapper now contains header chrome separately from the search composer.
Contract and browser validation
tests/header-scroll-hide-contract.test.ts, tests/ui-chrome-scroll.spec.ts
Tests verify wrapper separation, static positioning, and scrolling with page content across breakpoints.

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

Sequence Diagram(s)

sequenceDiagram
  participant Page as Page content
  participant Header as MasterSearchHeader
  participant Composer as Search composer
  Page->>Header: report scroll direction
  Header->>Header: hide or reveal top-bar chrome
  Page->>Composer: retain in-flow document position
  Composer->>Page: scroll with results content
Loading

Possibly related PRs

Suggested labels: codex

Suggested reviewers: cursoragent

🚥 Pre-merge checks | ✅ 4 | ❌ 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 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly matches the main change: keeping the tablet/desktop search page-anchored outside the sticky header.
Description check ✅ Passed The description includes summary, verification, risk/rollback, and notes, and it covers the key behavior change and tests run.
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.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch cursor/page-anchored-search-composer-30ee

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

Prettier re-indented the collapse sticky gate when the composer moved outside
the wrapper; match whitespace-flexibly so the contract stays stable.

Co-authored-by: BigSimmo <BigSimmo@users.noreply.github.com>
@github-actions

Copy link
Copy Markdown
Contributor

CI triage

CI failed on this PR. Automated classification of the 2 failed job(s):

  • Production UIneeds investigation: inspect the failing step and uploaded diagnostics; rerun only after classifying the cause.
  • PR requiredneeds investigation: inspect the failing step and uploaded diagnostics; rerun only after classifying the cause.

Compared with main CI run #5710 (success).

Classification is evidence routing, not permission to ignore a failure. Exact quarantined Playwright identities remain governed by the flake ledger.

@BigSimmo
BigSimmo marked this pull request as ready for review July 25, 2026 21:10
@BigSimmo
BigSimmo enabled auto-merge (squash) July 25, 2026 21:10

@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: a719225dc0

ℹ️ 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".

Comment thread src/components/clinical-dashboard/master-search-header.tsx Outdated
@BigSimmo

Copy link
Copy Markdown
Owner Author

@codex resolve actionable Codex review findings for this pull request and current head using the repository instructions. This is the pull request's single automatic repair pass: do not perform a fresh review, create new standalone findings, or request another review. Work only the existing unresolved Codex threads on the current head. Always fix P0 and P1 findings. For P2 and lower findings, fix only clear, scoped, low-risk issues; otherwise disposition them with a concise reason. After fixing or dispositioning a thread, reply in that thread with as the first line, followed by a concise summary; that marker authorizes the workflow to close that exact thread. If human input or new authorization is required, do not use the marker and leave the thread open with the blocker. Finish only after every actionable thread is fixed or dispositioned and closed, or explicitly left open for a human decision. Do not update the branch from main, address unrelated reviews, broaden scope, or create more than one scoped fix commit. Do not use external APIs, paid services, credentials, dependency changes, or broad refactors unless explicitly authorized. Add targeted tests where behavior changes and run the narrowest relevant validation.

@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

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/master-search-header.tsx (1)

1446-1463: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Gate the hero fallback class on desktopHomeComposerFallback, not isHeroDesktopComposer.

renderSearchComposer("default") is the inline fallback when the mode-home hero slot is unavailable, and the fallback is documented to keep search from vanishing. With desktopHomeComposerSlotId present and desktopHomeComposerFallback still false during the active portal path, isHeroDesktopComposer is true, so sm:hidden suppresses that fallback inline composer at tablet/desktop. Use isHeroDesktopComposer && !desktopHomeComposerFallback ? "sm:hidden" : null or otherwise gate on the portal failure state.

🤖 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/master-search-header.tsx` around lines 1446
- 1463, Update the conditional class selection in the composer className to
apply "sm:hidden" only when isHeroDesktopComposer is true and
desktopHomeComposerFallback is false. Preserve the fallback inline composer
visibility when the portal slot is unavailable, while leaving the existing
layout classes unchanged.
🧹 Nitpick comments (1)
tests/header-scroll-hide-contract.test.ts (1)

85-94: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Contract asserts on comment prose, which any reword breaks.

Line 90 pins an English sentence from a code comment, so a harmless comment edit fails the suite while a real regression (composer moved back inside the wrapper) could still pass. The behavioural assertions here are Lines 91–93 plus the new Playwright coverage; consider dropping the prose check or replacing it with a structural one (e.g. that searchComposerBlock is rendered as a sibling of universal-header-collapse, not a child).

🤖 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/header-scroll-hide-contract.test.ts` around lines 85 - 94, Update the
test named “keeps tablet/desktop search composers page-anchored outside sticky
header chrome” to remove the assertion on comment prose and replace it with a
structural assertion that searchComposerBlock is rendered as a sibling of
universal-header-collapse rather than inside it. Preserve the existing
behavioral class assertions and Playwright coverage.
🤖 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.

Outside diff comments:
In `@src/components/clinical-dashboard/master-search-header.tsx`:
- Around line 1446-1463: Update the conditional class selection in the composer
className to apply "sm:hidden" only when isHeroDesktopComposer is true and
desktopHomeComposerFallback is false. Preserve the fallback inline composer
visibility when the portal slot is unavailable, while leaving the existing
layout classes unchanged.

---

Nitpick comments:
In `@tests/header-scroll-hide-contract.test.ts`:
- Around line 85-94: Update the test named “keeps tablet/desktop search
composers page-anchored outside sticky header chrome” to remove the assertion on
comment prose and replace it with a structural assertion that
searchComposerBlock is rendered as a sibling of universal-header-collapse rather
than inside it. Preserve the existing behavioral class assertions and Playwright
coverage.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 7f53e256-0831-48f7-96ee-ec8b5385a977

📥 Commits

Reviewing files that changed from the base of the PR and between 644996b and a719225.

📒 Files selected for processing (5)
  • docs/search-chrome-behaviour.md
  • src/components/clinical-dashboard/global-search-shell.tsx
  • src/components/clinical-dashboard/master-search-header.tsx
  • tests/header-scroll-hide-contract.test.ts
  • tests/ui-chrome-scroll.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: a719225dc0

ℹ️ 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".

</div>
</div>
</div>
{searchComposerBlock}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Keep internal-scroll composers with their scroller

On tablet/desktop ClinicalDashboard result views such as /?mode=prescribing&q=a&run=1, this places the composer outside the collapse wrapper but still before the independently scrolling <main> (ClinicalDashboard.tsx uses overflow-y-auto). Scrolling the results therefore cannot move the supposedly page-anchored composer, so it remains as a permanent top band after the header hides instead of scrolling away with the content. Keep this composer in the collapsible region or render it inside the dashboard scrollport; the smallest regression proof is to extend the existing dashboard-results Playwright case and assert that the form's bottom leaves the viewport after scrolling <main>.

AGENTS.md reference: AGENTS.md:L214-L220

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

@codex fix this

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Summary

Testing

  • npx vitest run tests/header-scroll-hide-contract.test.ts — 11 tests passed.
  • npx vitest run tests/test-runner-safety.test.ts — focused rerun passed all 18 tests.
  • npm run test:e2e -- tests/ui-chrome-scroll.spec.ts --project=chromium — the isolated production build and TypeScript validation completed successfully.
  • ⚠️ npm run verify:cheap — all static, documentation, lint, and type checks passed; the suite reached 3,466 passing tests before three heavyweight-lock tests timed out under the environment load. Their focused rerun passed 18/18.
  • ⚠️ npm run test:e2e -- tests/ui-chrome-scroll.spec.ts --project=chromium — browser execution could not start because the required Playwright Chromium binary was absent.
  • ⚠️ npx playwright install chromium — Chromium download was blocked by HTTP 403 from the Playwright CDN, so browser screenshots could not be captured.
  • git diff --check — no whitespace errors.
  • git status --short --branch — worktree clean after commit.

View task →

@BigSimmo

Copy link
Copy Markdown
Owner Author

@cursoragent fix merge conflict please

@cursor

cursor Bot commented Jul 25, 2026

Copy link
Copy Markdown
Contributor

Taking a look!

Open in Web Open in Cursor 

Resolve search-chrome conflicts by keeping main's sticky-stack top-bar
hide behaviour from #1238/#1234, which supersedes the page-anchored
composer approach on this branch.

Co-authored-by: Cursor <cursoragent@cursor.com>
@BigSimmo

Copy link
Copy Markdown
Owner Author

Closing as superseded.

#1238 already landed the durable tablet/desktop chrome fix (sticky [top bar | search] stack; only the top bar collapses). After merging main to resolve conflicts, this PR has 0 files changed vs main, so there is nothing left to ship here.

@BigSimmo BigSimmo closed this Jul 26, 2026
auto-merge was automatically disabled July 26, 2026 00:13

Pull request was closed

@BigSimmo

Copy link
Copy Markdown
Owner Author

Hygiene review (2026-07-26): this PR is MERGEABLE against current main with green required checks (or Production UI finishing). Prior contaminated Antigravity originals were closed; this clean supersede/fix is the intended land path. No code change from this note — ready for human merge when review/blockers clear.

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.

2 participants