Skip to content

fix(widgets): handle dropdown viewport overflow and warn on missing anchor#174

Merged
RtlZeroMemory merged 3 commits intomainfrom
fix/dropdown-overflow-anchor-warning
Feb 23, 2026
Merged

fix(widgets): handle dropdown viewport overflow and warn on missing anchor#174
RtlZeroMemory merged 3 commits intomainfrom
fix/dropdown-overflow-anchor-warning

Conversation

@RtlZeroMemory
Copy link
Copy Markdown
Owner

@RtlZeroMemory RtlZeroMemory commented Feb 23, 2026

Summary

  • clamp dropdown overlay geometry to viewport height so long menus no longer overflow the terminal
  • budget an extra column for scrollbar space when dropdown content is taller than the viewport
  • emit a dev warning when a dropdown references an anchor id that cannot be resolved
  • add focused regression tests for dropdown geometry clamping and missing-anchor warning behavior

Testing

  • npm run build
  • node scripts/run-tests.mjs

Summary by CodeRabbit

  • New Features
    • Dropdown sizing now clamps to viewport and expands width when scrolling is required so content remains accessible.
  • Improvements
    • Development mode emits a single helpful warning when a dropdown's anchor cannot be found.
  • Tests
    • Added tests covering dropdown sizing behavior and the missing-anchor warning emission.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Feb 23, 2026

📝 Walkthrough

Walkthrough

Implements scroll-aware dropdown sizing that clamps height to the viewport and budgets width for a scrollbar when needed, and adds a development-only warning for missing dropdown anchors; includes tests for geometry behavior and the anchor-missing warning.

Changes

Cohort / File(s) Summary
Dropdown geometry
packages/core/src/layout/dropdownGeometry.ts, packages/core/src/layout/__tests__/dropdownGeometry.test.ts
Adds scroll-aware sizing: clamps dropdown height to viewport rows, increases width to account for scrollbar when clamped, and passes adjusted overlaySize to anchor positioning. Adds tests covering clamping, width budgeting, preserving sizes, and minimum geometry for empty lists.
Overlay dev warnings & tests
packages/core/src/renderer/renderToDrawlist/widgets/overlays.ts, packages/core/src/runtime/__tests__/overlayUnification.test.ts
Adds DEV_MODE flag, per-anchor warning guard, and warnDev helper to emit a single development-only console warning when a dropdown's anchorId is present but the anchor is missing. Adds a test that captures console.warn and asserts the warning is emitted once.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Poem

🐰
My whiskers count rows and columns wise,
I shrink the height and widen where scrolls rise.
In dev I softly call when anchors stray,
Tests nod and say the rabbit's found the way. 🥕

🚥 Pre-merge checks | ✅ 2 | ❌ 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 (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately describes the two main changes: handling dropdown viewport overflow by clamping geometry and warning on missing anchor references.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch fix/dropdown-overflow-anchor-warning

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

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

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: 33663aefda

ℹ️ 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 packages/core/src/renderer/renderToDrawlist/widgets/overlays.ts Outdated
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

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 the current code and only fix it if needed.

Inline comments:
In `@packages/core/src/layout/__tests__/dropdownGeometry.test.ts`:
- Around line 1-4: Imports in dropdownGeometry.test.ts are out of order per
Biome organizeImports; open the file and reorder the import statements (the ones
referencing computeDropdownGeometry, Rect, DropdownProps and the test utilities
import from "@rezi-ui/testkit") to match your project's Biome import ordering
rules, or simply run the Biome organizer/formatter (e.g., biome format or biome
organizeImports) to automatically fix the ordering and save the file.

In `@packages/core/src/layout/dropdownGeometry.ts`:
- Around line 31-37: When computing finalW for the overlay, guard against the
scrollbar-expanded width exceeding the viewport: if needsScroll is true, compute
the expanded width (totalW + 1) but clamp it to viewport.cols (e.g.,
Math.min(viewport.cols, totalW + 1)) so finalW never surpasses the visible
columns; update the calculation that sets finalW (referencing needsScroll,
totalW, viewport.cols, and finalW used in calculateAnchorPosition) to apply this
clamp.

In `@packages/core/src/renderer/renderToDrawlist/widgets/overlays.ts`:
- Around line 199-204: The warning block using DEV_MODE, anchor, props.anchorId
and warnDev needs Biome formatting; run the repo formatter (e.g., `biome check
--fix --unsafe` or the project's format command) to reformat the block around
the conditional that computes dropdownId and calls warnDev so the CI formatting
checks pass.

In `@packages/core/src/runtime/__tests__/overlayUnification.test.ts`:
- Around line 192-218: The test "warns when dropdown anchor id is missing"
currently instantiates WidgetRenderer directly; replace that with
createTestRenderer() from the testing module so the test uses the standard test
harness. Specifically, in this test swap new WidgetRenderer<void>({...}) for a
call to createTestRenderer() (ensuring it provides the same noop
backend/requestRender semantics the original used), keep the rest of the test
flow (submit, ui.dropdown with id "menu" and anchorId "missing-anchor",
captureConsoleWarn) unchanged, and run the same assertion to verify the warning
message.

Comment thread packages/core/src/layout/__tests__/dropdownGeometry.test.ts Outdated
Comment thread packages/core/src/layout/dropdownGeometry.ts
Comment thread packages/core/src/renderer/renderToDrawlist/widgets/overlays.ts Outdated
Comment thread packages/core/src/runtime/__tests__/overlayUnification.test.ts Outdated
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

🧹 Nitpick comments (2)
packages/core/src/layout/__tests__/dropdownGeometry.test.ts (2)

71-82: Good minimum bounds test.

Validates the Math.max(2, ...) guards in the implementation produce correct minimum geometry (3×2) for empty item lists.

Consider adding edge case tests for null anchor and zero-dimension viewport to complete coverage of the early-return paths in computeDropdownGeometry.

📝 Additional edge case tests
test("returns null when anchor is null", () => {
  const props = dropdownProps([{ id: "a", label: "item" }]);
  const viewport = { cols: 40, rows: 20 };
  
  const rect = computeDropdownGeometry(props, null, viewport);
  assert.equal(rect, null);
});

test("returns null when viewport has zero dimensions", () => {
  const props = dropdownProps([{ id: "a", label: "item" }]);
  const anchor: Rect = { x: 0, y: 0, w: 1, h: 1 };
  
  assert.equal(computeDropdownGeometry(props, anchor, { cols: 0, rows: 20 }), null);
  assert.equal(computeDropdownGeometry(props, anchor, { cols: 40, rows: 0 }), null);
});
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/core/src/layout/__tests__/dropdownGeometry.test.ts` around lines 71
- 82, Add unit tests covering the early-return branches of
computeDropdownGeometry: one test that passes a null anchor and asserts the
function returns null (use dropdownProps with at least one item and a normal
viewport), and one test that calls computeDropdownGeometry with an anchor and
viewports having cols === 0 and rows === 0 respectively and asserts null is
returned; place these tests alongside the existing cases in
dropdownGeometry.test.ts so computeDropdownGeometry, dropdownProps, and the
Rect/viewport shapes are imported/used consistently.

16-32: Tests correctly verify scroll-aware geometry calculations.

The test validates that:

  • Height is clamped to viewport rows (20) when items exceed viewport
  • Width includes +1 for scrollbar (6 → 7) when scrolling is needed

Minor style suggestion: assert.equal(rect.h <= viewport.rows, true) could be simplified.

💅 Prefer assert.ok() for boolean conditions
-    assert.equal(rect.h <= viewport.rows, true);
+    assert.ok(rect.h <= viewport.rows, "height should be clamped to viewport");
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/core/src/layout/__tests__/dropdownGeometry.test.ts` around lines 16
- 32, The boolean assertion in the test "clamps dropdown height to viewport and
budgets width for scrollbar" is verbose; replace the line that currently uses
assert.equal(rect.h <= viewport.rows, true) with a direct boolean assertion
using assert.ok(rect.h <= viewport.rows) to simplify and follow style
conventions—you can find this in the test that constructs items, calls
computeDropdownGeometry(props, anchor, viewport) and inspects rect.h and rect.w.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@packages/core/src/layout/__tests__/dropdownGeometry.test.ts`:
- Around line 71-82: Add unit tests covering the early-return branches of
computeDropdownGeometry: one test that passes a null anchor and asserts the
function returns null (use dropdownProps with at least one item and a normal
viewport), and one test that calls computeDropdownGeometry with an anchor and
viewports having cols === 0 and rows === 0 respectively and asserts null is
returned; place these tests alongside the existing cases in
dropdownGeometry.test.ts so computeDropdownGeometry, dropdownProps, and the
Rect/viewport shapes are imported/used consistently.
- Around line 16-32: The boolean assertion in the test "clamps dropdown height
to viewport and budgets width for scrollbar" is verbose; replace the line that
currently uses assert.equal(rect.h <= viewport.rows, true) with a direct boolean
assertion using assert.ok(rect.h <= viewport.rows) to simplify and follow style
conventions—you can find this in the test that constructs items, calls
computeDropdownGeometry(props, anchor, viewport) and inspects rect.h and rect.w.

@RtlZeroMemory RtlZeroMemory merged commit 07df442 into main Feb 23, 2026
31 checks passed
@RtlZeroMemory RtlZeroMemory deleted the fix/dropdown-overflow-anchor-warning branch February 23, 2026 07:00
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.

1 participant