Skip to content

fix(keyboard-actions): host the toolbar in the root overlay - #176

Merged
anilcancakir merged 4 commits into
masterfrom
fix/keyboard-actions-root-overlay
Aug 21, 2026
Merged

fix(keyboard-actions): host the toolbar in the root overlay#176
anilcancakir merged 4 commits into
masterfrom
fix/keyboard-actions-root-overlay

Conversation

@anilcancakir

@anilcancakir anilcancakir commented Aug 20, 2026

Copy link
Copy Markdown
Collaborator

What

WKeyboardActions inserts its toolbar into Overlay.of(context, rootOverlay: true) instead of the nearest overlay.

Why

The toolbar is positioned in screen terms, bottom: viewInsets.bottom, so it sits on top of the keyboard. A nested overlay is measured in its own box, so hosting it there positions it relative to content rather than the screen.

Measured on an iPhone, in an app whose page host owns an Overlay inside a scroll view: two overlays, one 402x874 (the screen) and one 402x2146 (the scrolled content), both reporting the same 335pt bottom inset. The entry went into the second, so bottom: 335 put the toolbar 335pt from the bottom of the CONTENT, roughly 1300pt below the viewport.

It was in the semantics tree the whole time and nowhere on the screen, which is the worst shape this bug can take: a tree assertion passes and the user still has nothing to press. Confirmed fixed on the device, with the button now sitting directly above the keyboard.

Testing

  • New case: an Overlay nested in a 2400pt scroll view, asserting the toolbar's rect stays within the screen height. Without the fix it reports 2400.0 against a 600.0 screen.
  • Full suite green: 1693 passed, 1 skipped.

Summary by CodeRabbit

  • Bug Fixes

    • Improved keyboard toolbar positioning when text fields appear inside nested overlays.
    • Ensured the toolbar remains correctly aligned with the screen and visible within the viewport while scrolling.
  • Tests

    • Added coverage for keyboard toolbar behavior in nested overlays and scrollable layouts.

Review pass (2026-08-21)

The original commit touched lib/ and test/ only, so the post-change sync CLAUDE.md requires was missing on four surfaces, and the interesting part of this fix is exactly the part nothing outside the implementation recorded: WHICH overlay hosts the toolbar.

  • The class doc comment said "renders an above-keyboard toolbar in the app's Overlay" with no qualification, which is the very ambiguity that caused the bug. It now names the root overlay and why.
  • doc/widgets/w-keyboard-actions.md was silent on overlay hosting. It now carries a note at the end of Basic Usage, including the reassurance that a consumer needs no Overlay of their own.
  • skills/wind-ui/references/theme.md section 12 covers OverlayEntry and stops at the theme-context caveat. Its snippet's Overlay.of(context) line was left alone deliberately: it demonstrates a content-anchored menu, where the nearest overlay is the right answer, so rewriting it to rootOverlay: true would teach the wrong default. A paragraph after it names host choice as the second, separate decision and uses this bug as the worked example.
  • CHANGELOG.md gained the ### Fixed entry.

README.md needs nothing (no roster change) and no example page is needed (no new token, and the bug only reproduces against a real keyboard inset).

Gates

Run locally on the branch tip:

  • dart format --set-exit-if-changed: 0 changed.
  • dart analyze lib/ test/ example/lib/: No issues found.
  • ./tool/coverage.sh 90: 1693 passed, 1 skipped, coverage 94.8%.
  • python3 tool/check-docs.py: 0 issues across 72 doc pages.

Lint & Test stays red here until #178 lands on master: flutter pub get rewrites analysis_options.yaml mid-run and dart pub publish --dry-run then fails on a dirty checkout. Nothing on this branch causes it.

The toolbar is positioned in SCREEN terms: `bottom: viewInsets.bottom`, so that
it sits on top of the keyboard. It was inserted into the NEAREST overlay, which
is measured in its own box, and a nested overlay is not the screen.

Measured on an iPhone in an app whose page host owns an Overlay inside a scroll
view: two overlays, one 402x874 (the screen) and one 402x2146 (the scrolled
content), both reporting the same 335pt inset. The entry went into the second, so
`bottom: 335` placed the toolbar 335pt from the bottom of the CONTENT, roughly
1300pt below the viewport. It was present in the semantics tree the whole time
and nowhere on the screen, which is the worst shape a bug like this can take: a
tree assertion passes and the user still has no button.

`rootOverlay: true` is the fix, and the new test is the shape that produced it:
an Overlay nested in a 2400pt scroll view, asserting the toolbar's rect stays
within the screen. It reports 2400 against a 600pt screen without the fix.
@coderabbitai

coderabbitai Bot commented Aug 20, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

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

Next review available in: 53 minutes

Limit details: You’ve used the included review currently available.

You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.

How can I continue?

Wait for the limit to reset, then comment @coderabbitai review or push new commits to the PR.

An organization admin can change what happens after included review limits in Billing.

How do review limits work?

CodeRabbit enforces per-developer PR review limits within each organization.

For paid Pro and Pro+ reviews, CodeRabbit uses a developer's included PR review attempts over the past 7 days to set the current hourly allowance. At typical activity levels, the full plan allowance applies. Higher sustained activity can lower the allowance until earlier attempts leave the 7-day window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 37fcf845-0191-4d6e-90ec-a7d27a3ae48a

📥 Commits

Reviewing files that changed from the base of the PR and between 78cef3a and 4bfb0a1.

📒 Files selected for processing (4)
  • CHANGELOG.md
  • doc/widgets/w-keyboard-actions.md
  • lib/src/widgets/w_keyboard_actions.dart
  • skills/wind-ui/references/theme.md

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: ca2a95d3-6790-4228-a7f9-16652aff1503

📥 Commits

Reviewing files that changed from the base of the PR and between d107740 and 78cef3a.

📒 Files selected for processing (2)
  • lib/src/widgets/w_keyboard_actions.dart
  • test/widgets/w_keyboard_actions_test.dart

Included review availability: Your plan provides up to 1 included review per hour; 0 remain after this review.


📝 Walkthrough

Walkthrough

WKeyboardActions now inserts its toolbar into the root overlay. A widget test verifies toolbar visibility within screen bounds when the widget is inside a nested overlay.

Changes

Keyboard toolbar placement

Layer / File(s) Summary
Root overlay insertion and regression coverage
lib/src/widgets/w_keyboard_actions.dart, test/widgets/w_keyboard_actions_test.dart
WKeyboardActions targets the root overlay instead of the nearest overlay. The regression test checks toolbar placement within screen bounds under a nested overlay.

Estimated code review effort: 2 (Simple) | ~10 minutes

Merge Risk: 🟡 Moderate · up to 78cef

The change keeps the keyboard toolbar above the keyboard instead of positioning it relative to scrolled content, fixing an off-screen user-facing issue. Merge readiness remains pending explicit results for analysis, formatting, and required coverage checks.

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check. Docstring coverage is scoped to functions touched by this diff. Analyzed 0 functions across 0 files. (2 skipped: 2 unsupported.)
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.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely describes moving the keyboard-actions toolbar to the root overlay, which is the main change.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/keyboard-actions-root-overlay

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.

@codecov

codecov Bot commented Aug 20, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

@anilcancakir

Copy link
Copy Markdown
Collaborator Author

@kodizm

2 similar comments
@anilcancakir

Copy link
Copy Markdown
Collaborator Author

@kodizm

@anilcancakir

Copy link
Copy Markdown
Collaborator Author

@kodizm

@kodizm

kodizm Bot commented Aug 21, 2026

Copy link
Copy Markdown

Note

Kodizm (AI-generated). May contain mistakes; verify before acting.

The one-line fix is correct - the toolbar is positioned in screen terms so the root overlay is the right host - and the only gap is the missing CHANGELOG entry the repo requires.

Major

CHANGELOG.md - no entry for this change (maintainability / repo rule). CLAUDE.md post-change sync surface #4 says every behaviour-changing source change lands a bullet under [Unreleased] in the same change set, and its stated acceptance check is grep -A 5 "^## \[" CHANGELOG.md. [Unreleased] currently carries only the skill and CI entries; nothing mentions WKeyboardActions. This belongs under ### Fixed.

Minor

lib/src/widgets/w_keyboard_actions.dart:220 - now that the entry lives in the root overlay it outranks anything pushed onto a nested Navigator, so a route or sheet opened while a listed focusNode still holds focus will render under the toolbar. Low likelihood (pushing a route normally drops focus and _removeOverlay fires), and it is strictly better than the invisible-toolbar bug being fixed - noting it only because the blast radius moved from "one subtree" to "the whole app".

The class docstring (line 11, "renders an above-keyboard toolbar in the app's Overlay") reads correctly after the change, and doc/widgets/w-keyboard-actions.md makes no claim about which overlay hosts the entry, so doc surfaces #1-#3 and #5 need nothing here.

Tests

The new WKeyboardActions overlay host case covers exactly the regression: nested Overlay in a 2400pt scroll view, asserting the toolbar rect stays inside the 600pt logical viewport. I could not verify the claimed pre-fix failure (2400.0 vs 600.0) - reverting the line in a scratch copy was not permitted in this environment - so that number is the author's measurement, not mine. Reasoning about the shape, it holds: the nested overlay is as tall as the SizedBox, so bottom: 0 there lands at y=2400.

Checks I ran

  • flutter test test/widgets/w_keyboard_actions_test.dart - 9 passed, 0 failed, including the new nested-overlay case.
  • dart format --set-exit-if-changed on both touched files - no diff.
  • dart analyze on both touched files - "No issues found!".
  • Did not run the full suite or ./tool/coverage.sh 90; the change is +8/-1 in one widget plus a test, so CI's gates are the cheaper place for those.

…l and changelog

The fix changed WHICH overlay hosts the toolbar, and nothing outside the
implementation said which one it was. The class doc claimed "the app's
Overlay" without qualification, `doc/widgets/w-keyboard-actions.md` was
silent, and the skill's OverlayEntry section covered the theme-context
caveat while never mentioning that host choice is a second, separate
decision.

Skill version 2.12.0.
Resolves the CHANGELOG conflict both entries created by claiming the first
bullet under `### Fixed`. Kept both, flex first because it landed first; no
wording changed on either side. `skills/wind-ui/SKILL.md` merged clean since
both branches set the same 2.12.0.
@anilcancakir
anilcancakir merged commit f5fc620 into master Aug 21, 2026
13 checks passed
@anilcancakir
anilcancakir deleted the fix/keyboard-actions-root-overlay branch August 21, 2026 11:20
@anilcancakir anilcancakir mentioned this pull request Aug 21, 2026
anilcancakir added a commit that referenced this pull request Aug 21, 2026
Minor release, not a patch. The Return-key default on a single-line `WInput`
moved from `TextInputAction.next` to `.done` (#177), which changes behaviour in
every consumer that never passed `textInputAction`. Consumers are pinned with
`^1.3.0`, so a patch would have landed that on everyone at the next
`pub upgrade` with the version number saying nothing had changed. A minor still
reaches them automatically, so the two layout fixes are not withheld, but the
number now says to read the notes.

Ships with those two fixes: a `justify-between` row no longer splits its width
between a child that asked to grow and siblings that did not (#175), and
`WKeyboardActions` hosts its toolbar in the root overlay so it lands on the
keyboard rather than hundreds of points below the viewport (#176). Plus the CI
fix that had every open PR red on a dirty checkout (#178) and the
codeql-action bump (#174).

Bump pubspec.yaml 1.3.0 -> 1.4.0 and promote ## [Unreleased] to
## [1.4.0] - 2026-08-21 in CHANGELOG.md, with the [1.4.0] link reference and
the [Unreleased] compare link redirected to 1.4.0...HEAD. Sync
example/pubspec.yaml, the dartdoc_options.yaml source-link tag, and the
llms.txt version string. Move the wind-ui skill to the 1.4 line: the nine
reference H1s plus the SKILL.md description and version marker.
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