Skip to content

Documents: present the filter panel as a sheet - #1542

Merged
BigSimmo merged 7 commits into
mainfrom
claude/top-search-design-mockups-w53znc
Jul 31, 2026
Merged

Documents: present the filter panel as a sheet#1542
BigSimmo merged 7 commits into
mainfrom
claude/top-search-design-mockups-w53znc

Conversation

@BigSimmo

@BigSimmo BigSimmo commented Jul 31, 2026

Copy link
Copy Markdown
Owner

Summary

  • Follow-up to Documents: one reachable filter panel, and a library control named after what it opens #1536 (merged). The filter panel it introduced was an in-flow block below the results ribbon, so on a phone it pushed the results down as it opened — the count it reports scrolled out of view exactly while you were tapping the controls that change it. It now renders through ui/sheet.tsx: bottom sheet with a drag grip below sm, centred dialog from sm up, focus trap and Escape included.
  • The panel body is unchanged. The header row becomes the sheet title plus headerActions (Clear all), and the count and "Show N documents" become the sheet footer, which keeps them pinned rather than stranded at the end of a long facet list.
  • The trigger is now a dialog opener: aria-haspopup="dialog" plus aria-expanded, and aria-controls pointing at the dialog via the id prop Sheet gained on main in feat(design-system): v2 token layer + 26 components — reconciled, cascade-ported, forced-colours owned #1538. No returnFocusRefSheet falls back to the previously focused element, which is the correct behaviour given two trigger copies (-phone / -wide) sit in the DOM and only one is ever displayed.
  • Mounted unconditionally rather than behind the open flag: Sheet returns null while closed and owns its own transition, so gating the mount would cut the dismiss animation off mid-flight. The query-scoped filterPanelState added on main is kept as-is, so a new search still cannot leave the sheet covering a different result set.

Verification

  • npm run verify:cheap — exit 0, Test Files 457 passed (457), Tests 4780 passed | 4 skipped (4784)
  • tests/document-filter-panel.dom.test.tsx — 9 passed, including two new cases for this change: the panel resolves to role="dialog" (it overlays the results rather than displacing them) and Escape dismisses it.
  • Browser proof: ui-smoke.spec.ts document search mode lists matching documents and result actions @critical — 1 passed, Chromium. The existing phone and wide assertions from Documents: one reachable filter panel, and a library control named after what it opens #1536 pass unchanged through the sheet.
  • npm run verify:phone-chrome on the pre-rebase commit: lock-parity, runtime and contract stages green; changed-browser 93 passed / 1 failed; the focused-browser stage the gate aborted before was then run directly — 7 passed.
  • The single changed-browser failure is document viewer puts the PDF preview first with pinned evidence after it on mobile, at pdfScroller.locator("canvas"). It fails identically with these changes stashed, so it is pre-existing and environmental: this box has Chromium 1194 against the project's pinned 1228, run via the PLAYWRIGHT_CHROMIUM_EXECUTABLE_PATH hook the config already supports.
  • npm run verify:pr-local — not run; the gates above are the evidence.
  • eval:*, check:production-readiness, check:supabase-project — not run and not applicable. No retrieval, ranking, ingestion, or provider surface is touched.

RAG impact: no retrieval behaviour change — this changes only how an already-built client-side filter panel is presented. No file under src/lib/rag/**, clinical-search, retrieval-selection, ranking-config, answer-ranking, the eval harness, or the golden fixture is touched, and no retrieval RPC or comparator ordering is altered.

Risk and rollout

  • Risk: presentation-only, confined to the documents results view. The filter semantics, counts, and dead-end handling are untouched. The behavioural change a reader will notice is that the panel now overlays the list instead of displacing it, and that Escape and backdrop click dismiss it.
  • Rollback: single commit, reverts cleanly without touching the panel's contents or the filter logic merged in Documents: one reachable filter panel, and a library control named after what it opens #1536.
  • Provider or production effects: None.

Clinical Governance Preflight

classifyPullRequestFiles returns clinicalRisk: false, operationalRisk: false, ragRanking: false, ui: true for this file set — the diff is src/components/clinical-dashboard/document-search-results.tsx and its DOM test only, and does not touch src/lib/document-tags.ts (which is what tripped the classifier on #1536). No ingestion, answer generation, search/ranking, source rendering, document access, privacy, or production-environment path is involved.

Notes


Generated by Claude Code

Summary by CodeRabbit

  • New Features

    • Improved the document filter panel with responsive presentation: a bottom sheet on small screens and a centered dialog on larger screens.
    • Added clearer filter controls, including a header action, live result count, and completion button.
    • Enhanced accessibility semantics for filter triggers and the panel.
  • Bug Fixes

    • The filter panel now closes reliably when pressing Escape.
  • Tests

    • Added coverage for dialog behavior, accessibility semantics, and Escape-key dismissal.

On a phone the in-flow panel pushed the results down as it opened, so the
count it reports scrolled out of view exactly while you were tapping the
controls that change it. `ui/sheet.tsx` already solves this: bottom sheet with
a drag grip below `sm`, centred dialog from `sm` up, focus trap and Escape
included.

The panel body is unchanged. The header row becomes the sheet title plus
`headerActions` (Clear all), and the count and "Show N documents" become the
sheet footer, which keeps them pinned above the fold rather than at the end of
a long facet list.

The trigger is now a dialog opener: `aria-haspopup="dialog"` with
`aria-expanded`, and no `aria-controls`, since the sheet owns its own id. No
`returnFocusRef` either — `Sheet` falls back to the previously focused element,
which is the correct behaviour with two trigger copies in the DOM.

Mounted unconditionally rather than behind `filterPanelOpen`: `Sheet` returns
null while closed and owns its own transition, so gating the mount would cut
the dismiss animation off mid-flight.

Verified: `npm run verify:cheap` exit 0, 450 files / 4712 tests passed.
`verify:phone-chrome` — lock-parity, runtime and contract stages green;
`changed-browser` 93 passed / 1 failed on the pre-existing document-viewer PDF
canvas test, which fails identically with these changes stashed under Chromium
1194 against the pinned 1228; the `focused-browser` stage it aborted before was
run directly, 7 passed.

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

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

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

The document filter panel now uses the shared Sheet component with controlled state, responsive dialog behavior, header and footer content, and dialog accessibility attributes. DOM tests cover overlay semantics and Escape-key closure.

Changes

Document filter sheet

Layer / File(s) Summary
Controlled Sheet integration
src/components/clinical-dashboard/document-search-results.tsx
The inline filter aside is replaced with a controlled, portal-backed Sheet. Header clear actions, live result counts, completion controls, responsive behavior, and conditional aria-controls handling are added.
Dialog interaction validation
tests/document-filter-panel.dom.test.tsx, docs/branch-review-ledger.md
DOM tests verify dialog semantics and Escape-key closure. The review ledger records the implementation and verification results.

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

Sequence Diagram(s)

sequenceDiagram
  participant FilterTrigger
  participant DocumentFilterPanel
  participant Sheet

  FilterTrigger->>DocumentFilterPanel: Open filter panel
  DocumentFilterPanel->>Sheet: Render controlled Sheet
  Sheet-->>DocumentFilterPanel: Close on Escape or completion
  DocumentFilterPanel-->>FilterTrigger: Update dialog attributes
Loading

Possibly related PRs

Suggested reviewers: claude, cursoragent

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and concisely describes the main change: presenting the documents filter panel as a sheet.
Description check ✅ Passed The description covers the required summary, verification evidence, risk, rollback, production effects, governance assessment, and notes.
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

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

@ecc-tools

ecc-tools Bot commented Jul 31, 2026

Copy link
Copy Markdown

🔒 Upgrade Required

Private repository analysis requires Pro or Enterprise.

Upgrade: https://ecc.tools/pricing?plan=pro


ECC Tools keeps the core app open, and puts private repos, team features, and enterprise controls behind paid tiers.

@BigSimmo
BigSimmo marked this pull request as ready for review July 31, 2026 14:23
@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.

@qodo-code-review

Copy link
Copy Markdown

Qodo reviews are paused for this user.

Troubleshooting steps vary by plan Learn more →

On a Teams plan?
Reviews resume once this user has a paid seat and their Git account is linked in Qodo.
Link Git account →

Using GitHub Enterprise Server, GitLab Self-Managed, or Bitbucket Data Center?
These require an Enterprise plan - Contact us
Contact us →

@ecc-tools

ecc-tools Bot commented Jul 31, 2026

Copy link
Copy Markdown

🔒 Upgrade Required

Private repository analysis requires Pro or Enterprise.

Upgrade: https://ecc.tools/pricing?plan=pro


ECC Tools keeps the core app open, and puts private repos, team features, and enterprise controls behind paid tiers.

@BigSimmo
BigSimmo enabled auto-merge July 31, 2026 14:25
@ecc-tools

ecc-tools Bot commented Jul 31, 2026

Copy link
Copy Markdown

🔒 Upgrade Required

Private repository analysis requires Pro or Enterprise.

Upgrade: https://ecc.tools/pricing?plan=pro


ECC Tools keeps the core app open, and puts private repos, team features, and enterprise controls behind paid tiers.

@ecc-tools

ecc-tools Bot commented Jul 31, 2026

Copy link
Copy Markdown

🔒 Upgrade Required

Private repository analysis requires Pro or Enterprise.

Upgrade: https://ecc.tools/pricing?plan=pro


ECC Tools keeps the core app open, and puts private repos, team features, and enterprise controls behind paid tiers.

@ecc-tools

ecc-tools Bot commented Jul 31, 2026

Copy link
Copy Markdown

🔒 Upgrade Required

Private repository analysis requires Pro or Enterprise.

Upgrade: https://ecc.tools/pricing?plan=pro


ECC Tools keeps the core app open, and puts private repos, team features, and enterprise controls behind paid tiers.

@BigSimmo

Copy link
Copy Markdown
Owner Author

@cursoragent Unblock the current open PR. Confirm the PR number and GitHub head first from context. If more than one open PR could apply, stop and say which one you would use and why.

Fetch and start from the remote tip that matches that GitHub head. If the named branch ref is missing or stale, use the PR head ref. Preserve unrelated local WIP; do not discard dirty work; do not treat a local-ahead commit as the reviewed tip. Do not merge the PR, force-push, rebase, or arm auto-merge. No provider-backed gates without approval. If you cannot push or resolve threads, diagnose and comment only; if inline replies fail, resolve when possible and put blocker dispositions in the summary comment. If auto-merge is already armed, push only for a real blocker and avoid cancelling in-flight required CI unless the push clears that blocker.

If the PR is already merged or closed: confirm outcome, post one summary, and stop.

Primary job: clear mergeability and required-CI blockers on this tip. Do a full product review only if needed to explain or fix a blocker. Stay light otherwise—no broad verification suites or Playwright unless needed to prove one concrete unblock fix.

Snapshot the GitHub head: tip, behind/ahead, mergeable state, merge-tree versus origin/main (real conflict versus behind-but-clean), required checks on that tip including Production UI when selected, and unresolved threads that block merge or required CI. Missing checks while dirty are not green. Tip moved → re-snapshot.

Ledger-lookup against that GitHub head under an unblock/fix scope for this PR. If already handled at this head for unblock work, merge-tree clean, required checks green, and no blocking threads: summarize, comment, stop.

Unblock once: real conflict → merge origin/main with the smallest correct resolution (prefer main’s shared queues; keep this PR’s notes); behind-but-clean → one sync, late if required CI is in flight; clean → leave. skip-branch-sync and similar labels do not block a manual sync needed to clear a real blocker. No sync thrash. After any sync or push, re-snapshot tip, merge-tree, and required checks before declaring done. Dedupe the ledger if a merge touched it.

Fix only what blocks required checks or mergeability on this tip. Ignore advisory red unless it reveals a real required failure. Prefer the smallest safe fix; if a bot/autofix commit caused the break, prefer revert. Prove with the smallest targeted check only. Format and commit before push.

Push only blocker-fix commits. Append ledger for the final GitHub head under the unblock scope. Never push a ledger-only tip.

One PR comment: tip, sync/merge-tree, what blocked and what you fixed or dispositioned, required CI status, residual risks; merge left to me.

Stop when merge-tree is clean on the current GitHub tip, no blocking threads remain for merge/required CI, and required checks are green or clearly in progress.

@cursor

cursor Bot commented Jul 31, 2026

Copy link
Copy Markdown
Contributor

PR #1542 unblocked (the dirty one; #1546/#1547 are unrelated behind-but-mergeable).

GitHub said CONFLICTING, but merge-tree vs main was clean — behind-but-clean after main moved to eba63dda. Synced once with git merge origin/main (no content conflicts) → tip 604ded62.

Now: MERGEABLE, merge-tree clean, 0 threads. Required CI re-running on the new tip. Auto-merge was already armed; no further push. Ledger kept local only. Merge left to you.

Open in Web Open in Cursor 

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

ecc-tools Bot commented Jul 31, 2026

Copy link
Copy Markdown

🔒 Upgrade Required

Private repository analysis requires Pro or Enterprise.

Upgrade: https://ecc.tools/pricing?plan=pro


ECC Tools keeps the core app open, and puts private repos, team features, and enterprise controls behind paid tiers.

@cursor

cursor Bot commented Jul 31, 2026

Copy link
Copy Markdown
Contributor

Unblock summary — PR #1542

Confirmed: open PR for this request is #1542 (claude/top-search-design-mockups-w53znc) — “Documents: present the filter panel as a sheet”. Other open PRs (#1546, #1547) are behind-but-mergeable and unrelated to the dirty mergeability failure in context.

Prior tip 77b829cc114e0803916ecea3d9b2960951d30f8a (GitHub head at start)
Current tip 604ded62b7bf7c155af07faecb0aab97cf953c44
Diagnosis GitHub CONFLICTING/DIRTY after maineba63dda, but git merge-tree --write-tree origin/main was clean (1 behind / 6 ahead) — behind-but-clean, not a content fight
Action One sync: git merge origin/main (ort auto-merge, no manual resolution). Pushed. Auto-merge was already armed — push only because dirty mergeability was a real blocker.
Now MERGEABLE; merge-tree clean; 0 behind main; 0 unresolved review threads

Required CI (tip 604ded62)

  • In progress: PR policy, PR mergeability, Semgrep, Gitleaks, autofix, and the broader CI jobs will follow — clearly in flight after the sync push.
  • Prior tip’s in-flight jobs were superseded by this sync (expected with cancel-in-progress).

Residual

  • Wait for required checks (incl. Production UI when selected) to finish on 604ded62.
  • Ledger row for this unblock head kept local only (no ledger-only tip).
  • Merge left to you / existing auto-merge.

@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

🤖 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/clinical-dashboard/document-search-results.tsx`:
- Around line 240-250: Update the footer action button in the document search
results component to use the 48px desktop tap target by replacing its
sm:min-h-10 class with sm:min-h-12, while preserving the existing min-h-tap and
other styling.
- Around line 1282-1288: Ensure DocumentFilterPanel remains mounted long enough
to receive open={false} and complete the Sheet close transition when loading or
query changes make showFilterControl false, or explicitly invoke the existing
onDone handler to close filterPanelState before unmounting. Update the relevant
mounting/close logic near DocumentFilterPanel and add a regression test covering
an open panel followed by a loading transition or new query, verifying focus
returns to the opener.

In `@tests/document-filter-panel.dom.test.tsx`:
- Around line 169-180: Expand the dialog interaction test around
DocumentSearchResultsPanel to assert the opened trigger has aria-expanded="true"
and an aria-controls value matching the rendered dialog’s id, while preserving
the existing role and aria-haspopup checks. After closing via Escape, assert
aria-expanded="false" and that aria-controls is removed from the trigger.
🪄 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: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: dc2cba3b-6bf1-46f2-bfdd-e81805c886f2

📥 Commits

Reviewing files that changed from the base of the PR and between eba63dd and 604ded6.

📒 Files selected for processing (3)
  • docs/branch-review-ledger.md
  • src/components/clinical-dashboard/document-search-results.tsx
  • tests/document-filter-panel.dom.test.tsx

Comment thread src/components/clinical-dashboard/document-search-results.tsx
Comment thread src/components/clinical-dashboard/document-search-results.tsx
Comment thread tests/document-filter-panel.dom.test.tsx
@BigSimmo
BigSimmo merged commit 58aeee6 into main Jul 31, 2026
45 checks passed
@BigSimmo
BigSimmo deleted the claude/top-search-design-mockups-w53znc branch July 31, 2026 15:43
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