Skip to content

hotfix(v3.1.9): render chat header dropdowns in a portal so they can't be clipped - #262

Merged
yalexx merged 2 commits into
mainfrom
hotfix/v3.1.9-dropdown-popover-clip
Jul 20, 2026
Merged

hotfix(v3.1.9): render chat header dropdowns in a portal so they can't be clipped#262
yalexx merged 2 commits into
mainfrom
hotfix/v3.1.9-dropdown-popover-clip

Conversation

@GeorgiK77

@GeorgiK77 GeorgiK77 commented Jul 20, 2026

Copy link
Copy Markdown
Contributor

Problem

The chat provider/model/reasoning dropdown menus are absolutely positioned and lived inside the chat popup, whose root has overflow: hidden. The 3.1.8 hotfix (#261) only lifted the clip on the .chat-header-pills row (fixing downward clipping), but the two right-hand pills' menus still overran the 400px popup's right edge and were cut off by the popup root's overflow — so the Model and Reasoning dropdowns appeared broken while Provider looked fine.

Fix

Render the popover through a React portal to <body> with viewport (fixed) coordinates, plus:

  • edge-shift — pull the menu back inside the viewport if it would overrun the right edge
  • flip-up — open above the pill when there's no room below
  • auto-height — cap the list to available space and scroll internally

No ancestor overflow can clip it now. Visual design is unchanged.

Bumps ClawBox 3.1.8 → 3.1.9 so boxes detect and pull the fix (tag v3.1.9 pushed).

Testing

  • bun run test — 1429/1429 pass
  • Production build (standalone) — clean, fix verified in the bundle
  • Deployed + verified live on a test box (gateway healthy, dropdowns open fully)

🤖 Generated with Claude Code

Summary by CodeRabbit

  • Bug Fixes

    • Improved header dropdown rendering and positioning to prevent clipping and keep menus visible at viewport edges.
    • Popovers now use fixed viewport coordinates, clamp to stay on-screen, and flip above the trigger when needed.
    • Dropdown content can scroll internally with improved height handling during resize and scrolling.
  • Tests

    • Added an end-to-end test to verify the chat provider dropdown remains visible within viewport margins.
  • Chores

    • Updated the application version to 3.1.9.

The chat provider/model/reasoning dropdown menus are absolutely
positioned and lived inside the chat popup, whose root has
`overflow: hidden`. The 3.1.8 hotfix only lifted the clip on the
`.chat-header-pills` row (fixing downward clipping), but the two
right-hand pills' menus still overran the 400px popup's right edge and
were cut off by the popup root's overflow.

Render the popover through a React portal to <body> with viewport
(fixed) coordinates, plus edge-shift (pull back inside the viewport)
and flip-up (open above when there's no room below), with the list
capped to available height and scrolling internally. No ancestor
overflow can clip it now. Visual design is unchanged.

Bump ClawBox 3.1.8 -> 3.1.9 so boxes detect and pull the fix.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@GeorgiK77
GeorgiK77 requested a review from a team as a code owner July 20, 2026 11:45
@coderabbitai

coderabbitai Bot commented Jul 20, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@yalexx, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 54 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

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: ASSERTIVE

Plan: Pro

Run ID: 1bb981ca-7e9b-48f7-959c-7b14e757126a

📥 Commits

Reviewing files that changed from the base of the PR and between 437e6c6 and 5c5d471.

📒 Files selected for processing (2)
  • e2e/chat-popup.spec.ts
  • src/components/HeaderDropdown.tsx
📝 Walkthrough

Walkthrough

Changes

Dropdown positioning

Layer / File(s) Summary
Viewport positioning and portal rendering
src/components/HeaderDropdown.tsx
HeaderDropdown computes constrained viewport coordinates, updates them on resize and scroll, links the trigger to the open listbox, and renders the fixed popover through document.body.
Viewport edge validation
e2e/chat-popup.spec.ts
The end-to-end test verifies provider-dropdown ARIA linkage and viewport margins at constrained chat-popup edges.

Package release metadata

Layer / File(s) Summary
Package version update
package.json
The package version changes from 3.1.8 to 3.1.9.

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

Sequence Diagram(s)

sequenceDiagram
  participant HeaderDropdown
  participant TriggerElement
  participant ViewportEvents
  participant document.body
  HeaderDropdown->>TriggerElement: Read bounding geometry
  HeaderDropdown->>ViewportEvents: Register resize and capture-phase scroll listeners
  HeaderDropdown->>HeaderDropdown: Compute constrained coordinates
  HeaderDropdown->>document.body: Render fixed popover through portal
  ViewportEvents->>HeaderDropdown: Trigger coordinate recomputation
Loading

Possibly related PRs

  • ID-Robots/clawbox#124: Introduces and redesigns the HeaderDropdown-based custom dropdown used in ChatPopup.

Suggested reviewers: krasimirkralev, yalexx

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the main change: rendering the chat header dropdowns in a portal to avoid clipping.
Description check ✅ Passed It explains the problem, fix, and testing results, covering most required information even though the template headings aren’t followed exactly.
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 unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch hotfix/v3.1.9-dropdown-popover-clip

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.

@github-actions

github-actions Bot commented Jul 20, 2026

Copy link
Copy Markdown

🦀 ClawReview

Poked my eyestalks out for this one. Quick tour:

Follow-up to the v3.1.8 hotfix (#261): where that PR lifted downward clipping on the chat header pill row, this one catches the remaining right-edge overflow on the Model and Reasoning menus by rendering the popover through a React portal directly to with fixed viewport coordinates. Edge-shift, flip-up, and auto-height capping ensure the popover stays fully on-screen regardless of where the chat window is positioned. Bumps the version to 3.1.9 so customer devices pull the fix via auto-update.

At a glance

  • 🔧 Fix · touches chat popup header dropdowns (HeaderDropdown.tsx + e2e tests)
  • Base branch: main · +76 source / +65 tests across 4 files
  • 🟡 targets main but touches device code — convention is beta-first (main carries tagged releases)
  • 🟡 package.json dependencies changed without bun.lock — CI runs bun install --frozen-lockfile and will fail
  • 🟡 title doesn't follow type: description (feat/fix/chore/docs/…)
  • ✅ source changes come with test changes

Good to know

  • 🟡 bun.lock is absent from the diff while package.json changed — CI runs bun install --frozen-lockfile and will fail if bun.lock is stale.
  • 🟡 Version bump to 3.1.9 triggers the auto-update path on customer hardware in the field.
  • ℹ️ Popover now renders outside the chat window's DOM subtree via createPortal; event bubbling from the popover won't reach listeners scoped inside the chat popup root.
  • ℹ️ E2E test exercises viewport-edge clamping for the provider dropdown; model and reasoning dropdowns share the same component but aren't separately exercised in the new test.

— ClawReview 🦀. I set the scene; CodeRabbit reviews the code; you decide. Conventions: docs.

@github-actions github-actions Bot added the area: ui Auto-triage area label Jul 20, 2026
@github-actions

github-actions Bot commented Jul 20, 2026

Copy link
Copy Markdown

CI Summary

✅ Tests

  • Result: passed
  • View run
  • Coverage: statements 70.01%, branches 59.8%, functions 65.45%, lines 72.04%

✅ E2E

✅ E2E Install

@coderabbitai coderabbitai 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.

Actionable comments posted: 4

🤖 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/HeaderDropdown.tsx`:
- Line 96: Replace the misleading Math.min(maxDesired, 160) expression in the
HeaderDropdown positioning condition with the constant threshold 160, or a
clearly named equivalent such as minPreferredHeight; leave the surrounding
spaceBelow and spaceAbove logic unchanged.
- Around line 70-114: Add targeted coverage in the e2e chat popup spec for the
positioning logic in HeaderDropdown’s useLayoutEffect: force a constrained
viewport or trigger position that exercises both vertical flip-above and
horizontal left-shift behavior, then verify the dropdown remains within the
viewport. Keep the existing basic open/select coverage unchanged.
- Around line 70-114: Throttle the HeaderDropdown useLayoutEffect recomputation
by wrapping compute() in a requestAnimationFrame scheduler that coalesces resize
and capture-phase scroll events into one update per frame. Ensure the scheduled
frame is canceled during effect cleanup and preserve the existing initial
computation and coordinate calculations.
- Around line 169-184: Add a stable unique id to the portaled listbox rendered
by HeaderDropdown and set the trigger button’s aria-controls to that same id,
while preserving the existing aria-haspopup and open-state behavior. Update the
relevant trigger and popover markup so assistive technologies can associate them
despite the portal.
🪄 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: ASSERTIVE

Plan: Pro

Run ID: 30e5b730-9106-446f-8b81-38e1ad361457

📥 Commits

Reviewing files that changed from the base of the PR and between 3c09ddc and 98eb276.

⛔ Files ignored due to path filters (1)
  • package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (2)
  • package.json
  • src/components/HeaderDropdown.tsx

Comment thread src/components/HeaderDropdown.tsx
Comment thread src/components/HeaderDropdown.tsx Outdated
Comment thread src/components/HeaderDropdown.tsx
@yalexx
yalexx enabled auto-merge July 20, 2026 12:02
@github-actions github-actions Bot added the area: ci-e2e Auto-triage area label Jul 20, 2026
@yalexx
yalexx force-pushed the hotfix/v3.1.9-dropdown-popover-clip branch from 437e6c6 to 5c5d471 Compare July 20, 2026 12:12
@yalexx
yalexx merged commit 49ab98c into main Jul 20, 2026
8 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area: ci-e2e Auto-triage area area: ui Auto-triage area

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants