Skip to content

fix(search-band): drop the sort segments from the phone results bar - #1689

Merged
cursor[bot] merged 6 commits into
mainfrom
claude/search-bar-mobile-layout-buu0io
Aug 7, 2026
Merged

fix(search-band): drop the sort segments from the phone results bar#1689
cursor[bot] merged 6 commits into
mainfrom
claude/search-bar-mobile-layout-buu0io

Conversation

@BigSimmo

@BigSimmo BigSimmo commented Aug 7, 2026

Copy link
Copy Markdown
Owner

Summary

  • Drop the sort segments ("Relevance" / "A–Z") from the shared results band below sm. The band puts count, query, sort and Filter on one line; on a phone those two segments take roughly half of it, so the query truncates to pay for a control that is set about once a session and already defaults to the order a phone reader wants. ResultSortControl is now hidden … sm:inline-flex, unchanged from 640px up.
  • Only the affordance is sm-and-up, not the ordering: ?sort=alpha still carries an alpha order onto a phone from a link or a wider session, and the results honour it.
  • The display class lives in the component's own base string rather than in a caller's className, because cn in this repo is a plain string join with no Tailwind conflict resolution — a base inline-flex plus a caller's hidden would have resolved by stylesheet order rather than by intent.
  • Add hasPhoneUtilities: a page whose only utility is sort (forms) would otherwise keep the utilities group mounted on a phone as an empty flex child, and in inline placement below 414px that child is w-full basis-full — a blank second line under the count.
  • Move the sort coverage rather than deleting it. ui-smoke now asserts the group is hidden at 390px and exercises the A–Z/Relevance interaction at the 1440px viewport the same test already resizes to; the two ui-tools differentials phone tests assert hidden while keeping the 44px tap-height floor on the page filter.
  • Fix the 320–540px utility-rail clip sweep, which located the control by aria-label="Sort results". With sort hidden below sm that node has no box, so the sweep would have measured zero at every width in its own range and passed blindly; it now measures the last rendered child of the track.
  • Update docs/search-chrome-behaviour.md rule 3, which is the contract of record for this band.

RAG impact: no retrieval behaviour change — presentation-only. No file under src/lib/rag/**, result-sort.ts, ranking/selection, the eval harness or the golden fixture is touched; sortResultItems and the default relevance order are unchanged, and the ?sort= URL contract still applies at every width.

Verification

  • npm run verify:pr-localTest Files 1 failed | 519 passed (520) · Tests 1 failed | 5527 passed | 4 skipped (5532). The single failure is tests/pr-handoff-stop.test.ts > emits handoff context only when the marker file exists, which is a session-hook environment artefact: it reproduces identically on the unmodified base commit (Test Files 1 failed (1) · Tests 1 failed | 10 passed (11) at e085154, with this diff checked out to nothing).
  • npm run lint — clean, --max-warnings 0.
  • npm run typecheck — clean.
  • npm run test:focused -- --files src/components/clinical-dashboard/search-results-header-band.tsxTest Files 9 passed (9) · Tests 117 passed (117).
  • npm run verify:phone-chrome — lock-parity and runtime PASS; contracts Test Files 9 passed (9) · Tests 118 passed (118); changed-browser (tests/ui-smoke.spec.ts + tests/ui-tools.spec.ts, chromium) 1 failed · 185 passed (5.8m). The one failure is document viewer puts the PDF preview first with pinned evidence after it on mobile, failing on getByTestId('pdf-canvas-scroll').locator('canvas') never appearing — a PDF.js canvas that does not render in this container, unrelated to the results band. Baselined: the same test fails identically at e085154 with this diff checked out to nothing. Every band journey passed, including document search mode lists matching documents and result actions @critical and both differentials narrow-viewport tests.

UI verification not run: npm run verify:ui was not run as a separate gate. npm run verify:phone-chrome is this repo's selector for phone-chrome scope and it reported "Focused ownership and journey coverage is sufficient for this page-local or test-infrastructure scope. Full UI policy: auto (not selected)" — its changed-browser stage already ran the complete ui-smoke + ui-tools chromium sets (186 tests), which is where every assertion about this band lives. Firefox/WebKit and physical Safari/installed-PWA acceptance remain uncovered, as always in a container.

Risk and rollout

  • Risk: low, and presentation-only. The blast radius is the eight surfaces rendering SearchResultsHeaderBand, and the change is a responsive display class plus one derived boolean — no state, data, route or ordering logic moves. The real user-facing cost is stated plainly rather than hidden: a phone can no longer switch to alphabetical from the bar. Relevance is the default so the common path is unaffected, and ?sort=alpha still works, but if alphabetical needs to stay reachable on a phone the natural home is the existing phone filter sheet — deliberately left as a follow-up rather than smuggled into this diff.
  • Rollback: revert this commit. It is self-contained in one component plus its tests and doc; nothing else imports ResultSortControl.
  • Provider or production effects: None. No provider-backed gate was run — all verification above is local and offline.

Notes

  • Two environment findings, neither caused by this diff, both worth knowing:
    • This session's checkout was ~80 PRs behind origin/main, and the band had been substantially rewritten in the interval (Results bar: one line, one filter, nothing unreachable #1615's one-line collapse). The first attempt was discarded and the change re-applied on current main.
    • Current main cannot npm ci on Node 24.13.0: jsdom@30.0.1 requires ^22.22.2 || ^24.15.0 || >=26.0.0, which engine-strict rejects. Node 24.15.0 was installed locally to get a lock-parity-clean install; package.json still declares 24.x, so this is an environment note, not a repo change.

Summary by CodeRabbit

  • New Features

    • Improved responsive search results controls: sorting is available on larger screens while phone layouts prioritize visible filters and query space.
    • Prevented empty utility rows and clipping of search controls on narrow screens.
  • Bug Fixes

    • Improved mobile tap-target behavior and layout handling for search filters.
  • Tests

    • Updated accessibility, smoke, and responsive UI coverage for the revised search controls.
  • Documentation

    • Clarified responsive sorting behavior and utility visibility.

The shared results band puts count, query, sort and Filter on one line. On
a phone the two sort segments ("Relevance" / "A-Z") take roughly half of
that line, so the query truncates to pay for a control that is set about
once a session and already defaults to the order a phone reader wants.

ResultSortControl is now sm-and-up. Only the affordance moves: `?sort=`
still carries an alpha order onto a phone from a link or a wider session,
and the results honour it. The display class lives in the component's own
base string because `cn` here is a plain join with no Tailwind conflict
resolution, so a caller's `hidden` would resolve by stylesheet order
rather than by intent.

Pages whose only utility is sort (forms) would have kept an empty
utilities group mounted on a phone -- and in `inline` placement below
414px that child is `w-full basis-full`, i.e. a blank second line. Guard
it with hasPhoneUtilities.

Tests move rather than disappear: ui-smoke asserts the group is hidden at
390px and exercises the A-Z/Relevance interaction at the 1440px viewport
the same test already resizes to, and the two ui-tools differentials
phone tests assert hidden while keeping the 44px tap floor on the page
filter. The 320-540px clip sweep measured the sort node by name, which
would have measured a display:none element and passed blindly at every
width; it now measures the last rendered control.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013mcqh46SDdiR5KxScihkFQ
@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.
To continue using code reviews, add credits to your account and enable them for code reviews in your settings.

@supabase

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

Copy link
Copy Markdown
Contributor

Review Change Stack

Warning

Review limit reached

You’ve reached a temporary PR review limit under our Fair Usage Limits Policy.

Your recent review volume is higher than typical usage, so adaptive limits are currently applied.

Next review available in: 13 minutes

Your organization has reached its usage spending cap. Adjust your spending cap in the billing tab.

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 6dbb392c-8c5f-4eb2-ad14-b27371ffeab8

📥 Commits

Reviewing files that changed from the base of the PR and between 669640b and a152ffd.

📒 Files selected for processing (4)
  • docs/search-chrome-behaviour.md
  • lighthouse-budget.json
  • tests/ui-smoke.spec.ts
  • tests/ui-tools.spec.ts
📝 Walkthrough

Walkthrough

The search results header now hides sort controls below sm, preserves URL-driven sorting on phones, and hides empty utility groups. UI tests cover the responsive layout. Lighthouse desktop and mobile baselines are refreshed.

Changes

Responsive search utilities

Layer / File(s) Summary
Responsive header behavior
docs/search-chrome-behaviour.md, src/components/clinical-dashboard/search-results-header-band.tsx
Sort controls render from sm upward. Phone queries still honor ?sort=. Sort-only utility groups are hidden below sm.
Responsive UI validation
tests/ui-accessibility.spec.ts, tests/ui-smoke.spec.ts, tests/ui-tools.spec.ts
Tests verify phone visibility, utility clipping, tap-target sizing, and desktop sort interactions.

Lighthouse baselines

Layer / File(s) Summary
Baseline measurement refresh
lighthouse-budget.json
Desktop and mobile route metrics, Chrome metadata, and the baseline timestamp are updated.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Browser
  participant SearchResultsHeaderBand
  participant ResultSortControl
  Browser->>SearchResultsHeaderBand: Render search results at viewport width
  SearchResultsHeaderBand->>ResultSortControl: Apply responsive visibility
  Browser->>SearchResultsHeaderBand: Provide URL sort query
  SearchResultsHeaderBand->>ResultSortControl: Preserve URL-driven sorting
Loading

Possibly related PRs

Suggested reviewers: claude, cursoragent, copilot

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and concisely describes hiding sort segments from the phone results bar.
Description check ✅ Passed The description covers the change, behavior, tests, known failures, risks, rollback, and verification status in detail.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
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 claude/search-bar-mobile-layout-buu0io

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

@BigSimmo
BigSimmo enabled auto-merge (squash) August 7, 2026 13:34
@BigSimmo
BigSimmo disabled auto-merge August 7, 2026 13:34
@BigSimmo
BigSimmo enabled auto-merge (squash) August 7, 2026 13:38
Copilot AI and others added 2 commits August 7, 2026 21:47
The HeadlessChrome/151 baseline refresh landed with `0.060` / `0.080`
trailing zeros, which Prettier normalises to `0.06` / `0.08`. That is the
whole diff -- no measurement changes. `format:changed` runs Prettier over
the PR's entire changed set, so the unformatted blob failed the required
Static PR checks job on this branch.

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

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

🤖 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 `@lighthouse-budget.json`:
- Around line 57-69: Regenerate the mobile-documents-search and mobile-dsm
baseline records in lighthouse-budget.json from the complete Lighthouse report
set, preserving the generated metric ordering with fcpMs before lcpMs. Add a
focused validation check that rejects any baseline row where lcpMs is less than
fcpMs.

In `@tests/ui-smoke.spec.ts`:
- Around line 3558-3563: At tests/ui-smoke.spec.ts lines 3558-3563,
tests/ui-tools.spec.ts lines 1663-1665, and tests/ui-tools.spec.ts lines
1767-1769, replace the existing “Sort results” visibility assertions with
getByRole("group", { name: "Sort results", includeHidden: true }); assert the
group has count 1, then assert it is hidden.
🪄 Autofix

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

Run ID: 765cdf3b-8f30-42bc-839b-5bf7027cff37

📥 Commits

Reviewing files that changed from the base of the PR and between da66b28 and 669640b.

📒 Files selected for processing (6)
  • docs/search-chrome-behaviour.md
  • lighthouse-budget.json
  • src/components/clinical-dashboard/search-results-header-band.tsx
  • tests/ui-accessibility.spec.ts
  • tests/ui-smoke.spec.ts
  • tests/ui-tools.spec.ts

Comment thread lighthouse-budget.json
Comment thread tests/ui-smoke.spec.ts Outdated
claude and others added 2 commits August 7, 2026 14:01
… absent

The three phone assertions claimed a guarantee they did not provide.
`toBeHidden()` passes for a hidden node AND for a node that does not
exist, and in ui-tools the plain `getByRole` locator filters hidden nodes
out before the assertion sees them -- so both would have passed with
ResultSortControl deleted from the component entirely, which is exactly
the regression the comment says they catch.

Resolve the group with `includeHidden: true`, assert `toHaveCount(1)`,
then assert `toBeHidden()`. A deleted control now fails the count; a
control returned to the phone line fails the visibility.

Raised by CodeRabbit on #1689.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013mcqh46SDdiR5KxScihkFQ
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.

4 participants