mockup: adaptive refine bar for the global search results header - #1457
Conversation
Adds /mockups/search-refine-adaptive, the selected direction for the shared
results header (SearchResultsHeaderBand, rendered at twelve call sites).
The band splits by stability rather than by kind. Row one holds what is always
present and must never move — the count, and the controls acting on the result
set. Row two holds only the active filter chips and is not rendered at all when
none are applied, so the common unfiltered search is a single line.
Settled in design review and reflected here:
- No query echo. The composer already shows the query with its own clear
button, so repeating it spent a heading rank and ~90px of width. Removing it
is also what lets row two disappear, since the row becomes purely filters.
- No source-composition prose and no corpus size while searching. Both were the
only reason the summary row existed; without them the row is gone.
- No accent border, magnifier tile, gradient pipe rule, display-weight query or
doubled count.
- One control species at one height and one label vocabulary
(label + value + count), replacing Show / Filter / Pattern / Domain.
- Sort and Sources sit outside the scroll container, so filter chips can never
push them off screen.
- An applied filter reports what it cost ("4 matches of 6"); a filtered-to-
nothing search names the blocking filter and offers the one-tap way out, so it
no longer looks identical to an empty index.
- aria-live wraps the count alone rather than the whole status span.
Controls are sized to the band's real floors (min-h-tap 44px phone,
sm:min-h-10 40px desktop) via an explicit compact flag, because the phone frame
renders inside a wide page where viewport variants would resolve incorrectly.
Mockup only — no production route, component or behaviour is touched, and
/mockups/* 404s in production.
Verified: npm run verify:cheap exit 0 (27 static gates && lint && typecheck &&
test — 434 files, 4563 passed). Route checked in Chromium at localhost:4598:
200, no page errors, and the adaptive row confirmed mounting and unmounting
across the unfiltered, one, three, zero and failed states.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JdPa3mHCX5ZQZZvU5GHU3r
|
This pull request has been ignored for the connected project Preview Branches by Supabase. |
|
Warning Review limit reachedYou’ve reached a temporary PR review limit under our Fair Usage Limits Policy. Next review available in: 58 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 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 configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (5)
Comment |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 46cd597617
ℹ️ 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".
|
@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. |
…e region Codex review, P2. On the searching -> error transition the count region was switched to aria-live="off", so a screen-reader user whose focus is elsewhere was never told the search had failed, nor that Retry had appeared — left waiting on a result that was not coming. The region now escalates to role="alert" / aria-live="assertive" on failure and stays polite otherwise, so an in-flight search still does not interrupt but a failure always reaches the user. Failure is the one transition that must not be muted. This mirrors aria-live="off" as set by the shipped band (search-results-header-band.tsx), so the same defect exists in production today. Out of scope for a mockup PR; captured for the production pass rather than fixed here. Adds a focused DOM assertion covering the transition. Verified non-vacuous: restoring aria-live="off" fails it with "Unable to find an accessible element with the role alert". Verified: npm run verify:cheap exit 0 (437 files, 4575 passed, 4 skipped). Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01JdPa3mHCX5ZQZZvU5GHU3r
…mzl' into claude/global-search-mockups-mrgmzl
|
Codex couldn't complete this request. Try again later. |
…ecord The two Services viewport-anchor data points from PR #1457 were dropped when the withdrawn #149 row and its id allocation were restored. They are unrelated to that decision, so this puts them back and changes nothing else. #149 stays exactly as set: archived as a withdrawn record, with issues:next-id preserved at 150 so the id is retired rather than reused. Restored to #146: the test failed once more on head c739340 (anchorTop expected -138, received -7) then passed on 9da02d9 and a6f2281 across all three shards with the spec byte-identical — six data points, two failures, shard 1 only, both failures on a mockups-only PR. Notes that the 131px delta is roughly 2x the 64px viewport shrink rather than sub-pixel drift, which constrains the element attribution that row already asks for. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01JdPa3mHCX5ZQZZvU5GHU3r
…#1481) * issues: capture the production live-region defect; record the landed #1457 review Adds #147 — `search-results-header-band.tsx` sets aria-live="off" when faulted, so a clinical search that fails while focus is elsewhere is announced to nobody and the user is never told Retry appeared. Affects all twelve call sites that render the band. Raised by Codex against the copied line on PR #1457, fixed there, and confirmed to exist unchanged in production. The merged mockup carries the proven pattern and a non-vacuous assertion to port. Appends two further data points to #146 from PR #1457: the Services viewport anchor failed once more on head c739340 (expected -138, received -7) and then passed on two later heads with the diff byte-identical — six data points, two failures, shard 1 only. Both failures landed on a PR touching only mockups, which strengthens the unchanged-code reading. Notes that the 131px delta is roughly 2x the 64px shrink rather than sub-pixel drift. Records the prlanded verification for PR #1457 in the branch review ledger: squash e79e499, content diff against the branch tip empty, and the late aria-live/role="alert" commit confirmed present on main rather than orphaned by the squash. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01JdPa3mHCX5ZQZZvU5GHU3r * issues: withdraw #149 — the live-region defect was false, and the fix was worse Codex caught this on PR #1481 and it is correct. I filed #149 claiming a failed clinical search is announced to nobody because the count span sets aria-live="off" when faulted. I never checked whether another node makes the announcement. It does. search-results-header-band.tsx mounts a fault panel with role="alert" carrying the failure title, body and Retry (lines 407-414), and the mute is deliberate, documented in place: "While faulted the live region is silenced (aria-live='off') and the freshly-mounted fault role='alert' below makes the single announcement, rather than both speaking." tests/search-results-header-band.dom.test.tsx already pins exactly that with singular role queries that throw on duplicates. Escalating the count span in production, as #149 recommended, would have added a second alert beside the fault panel — a duplicate announcement and a broken test. The row is withdrawn to the archive rather than deleted, with the reasoning recorded so nobody re-files it. The mockup is unaffected: search-refine-adaptive-mockups.tsx has no fault panel, so there the count span is the only announcement channel and its escalation is correct. It simply does not port to production. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01JdPa3mHCX5ZQZZvU5GHU3r * docs: record PR 1481 review * docs: preserve issue 149 allocation * docs: format withdrawn issue record * issues: restore the #146 data points lost while preserving the #149 record The two Services viewport-anchor data points from PR #1457 were dropped when the withdrawn #149 row and its id allocation were restored. They are unrelated to that decision, so this puts them back and changes nothing else. #149 stays exactly as set: archived as a withdrawn record, with issues:next-id preserved at 150 so the id is retired rather than reused. Restored to #146: the test failed once more on head c739340 (anchorTop expected -138, received -7) then passed on 9da02d9 and a6f2281 across all three shards with the spec byte-identical — six data points, two failures, shard 1 only, both failures on a mockups-only PR. Notes that the 131px delta is roughly 2x the 64px viewport shrink rather than sub-pixel drift, which constrains the element attribution that row already asks for. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01JdPa3mHCX5ZQZZvU5GHU3r --------- Co-authored-by: Claude <noreply@anthropic.com>
Summary
/mockups/search-refine-adaptive— the selected design direction for the shared search results header (SearchResultsHeaderBand, rendered at twelve call sites). The band splits by stability rather than by kind: row one holds what is always present and must never move (the count, and the controls acting on the result set), row two holds only the active filter chips and is not rendered at all when none are applied, so the common unfiltered search is a single line.label + value + count), replacing the Show / Filter / Pattern / Domain split across modes.aria-livewraps the count alone rather than the whole status span, so a refetch does not re-announce the controls.min-h-tap44px phone,sm:min-h-1040px desktop) through an explicitcompactflag, because the phone frame renders inside a wide page where viewportsm:variants would resolve against the page rather than the frame.docs/site-map.mdvianpm run sitemap:update, and adds the shared-chrome opt-out inmockups-layout-client.tsxso the shell composer cannot be mistaken for a second, real search bar over the study.Mockup only. No production route, component or behaviour is touched, and
/mockups/*returns 404 in production.Verification
npm run verify:pr-local— exit 0. Build compiled in 37.0s, 1695 static pages generated, client-bundle secret scan passed,check:rag:fixturespassed (36 golden cases, 21 suites), unit suite 434 files / 4563 passed / 4 skipped.npm run verify:cheap— exit 0 across the&&-joined chain of 27 static gates plus lint, typecheck and the full offline unit suite, includingsitemap:checkandcheck:design-system-contract.UI verification not run:
npm run verify:uicannot run in this container — the installed Playwright package expects a browser build (chromium_headless_shell-1234) that is not present, and onlychromium-1194is available. Verified directly in that Chromium instead against the local dev server: route returns 200 with no page errors, and the adaptive row was confirmed mounting and unmounting across the unfiltered, one-filter, three-filter, zero and failed states, withAdd filtercorrectly disabling once every filter is applied. This is a mockup route, excluded from the production journeysverify:uicovers.RAG impact: no retrieval behaviour change — this adds a design-scratch mockup route only and touches nothing under
src/lib/rag/**, clinical-search, retrieval-selection, ranking-config, answer-ranking, the eval harness or the golden fixture.check:rag:fixturespassed unchanged.Risk and rollout
/mockups/**is development-only, noindexed, and 404s in production; the only shared file touched ismockups-layout-client.tsx, where the change is one additional pathname flag guarding chrome visibility for this route alone.Notes
ui-smokerule.docs/search-chrome-behaviour.mdif the band ever becomes sticky.Generated by Claude Code