Skip to content

fix(input): default a single-line field's Return key to done - #177

Merged
anilcancakir merged 4 commits into
masterfrom
fix/single-line-return-dismisses
Aug 21, 2026
Merged

fix(input): default a single-line field's Return key to done#177
anilcancakir merged 4 commits into
masterfrom
fix/single-line-return-dismisses

Conversation

@anilcancakir

@anilcancakir anilcancakir commented Aug 20, 2026

Copy link
Copy Markdown
Collaborator

What

WInput defaults a single-line field to TextInputAction.done instead of TextInputAction.next. Multiline keeps newline. An explicit textInputAction still wins.

Why

Flutter resolves next to focusNode.nextFocus(), which is the next FOCUSABLE widget rather than the next text field. On a real form the traversal order runs through buttons, colour swatches and switches, so the same Return key did two different things on one screen.

Measured on a status-page form whose order is Name → [segmented control] → Slug → [8 colour swatches] → [Replace/Remove] → Initials → Description:

  • Return on Name focused the segmented-control button, so iOS dismissed the keyboard: nothing editable held focus.
  • Return on Initials happened to land on the Description textarea, so the keyboard stayed and the caret jumped.

Reported by a user as "why does Enter close the keyboard on one field and move to another on the next one". A key labelled Next that lands on a colour swatch is worse than one labelled Done.

Field-to-field advance stays available through textInputAction, and that is the only place the intent can be stated correctly: only the form knows its own field order.

Testing

  • The default assertion flips to done and gains a companion asserting an explicit next still wins, so the default cannot be hardcoded past the parameter.
  • Full suite green: 1693 passed, 1 skipped.

Review pass (2026-08-21)

The original commit touched lib/ and test/ only, so the post-change sync CLAUDE.md requires was missing. Nothing in doc/ or the skill stated the OLD default either, which is its own problem: a reader had no way to know what the Return key would do without running the app.

  • doc/widgets/w-input.md props table said only "Keyboard action (e.g. .done, .next)". It now states the resolved default, and the Event Handling section carries the reasoning: .next is focusNode.nextFocus(), so it is an opt-in for the case where the next focusable IS the next input.
  • skills/wind-ui/references/forms.md had no guidance on this at all, which is the surface an agent reads while composing a form. New section 10 covers the default, the per-field .next pattern, and points at WKeyboardActions for an explicit advance order.
  • CHANGELOG.md gained a ### Changed entry flagged as a behavioural break, with the one-line path back for a form that relied on the old default.
  • Skill 2.12.0.

README.md needs nothing (no roster change). No example page change: nothing under example/lib/ passes textInputAction, so no demo promised the old behaviour.

Note on the CHANGELOG section

This landed under ### Changed, not ### Fixed. It is a bug fix in intent, but it changes the default behaviour of a public widget, and a consumer whose form happened to be ordered as a clean run of adjacent fields loses the Return-advances-field behaviour on upgrade. Filing it as a fix would hide that from anyone reading the release notes for breaking changes.

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 default was `next`, and Flutter resolves `next` to `focusNode.nextFocus()`:
the next FOCUSABLE widget, not the next text field. On a real form the traversal
order runs through buttons, colour swatches and switches, so one Return key
behaved two different ways on one screen. Measured on a status-page form: Return
on Name moved focus to a segmented-control button and iOS dismissed the keyboard
because nothing editable held focus, while Return on the field below happened to
land on a textarea, so the keyboard stayed and the caret jumped. A key labelled
Next that lands on a colour swatch is worse than one labelled Done.

`done` is now the default, so Return does one predictable thing. Field-to-field
advance is still available through `textInputAction`, and that is the only place
the intent can be stated correctly: only the form knows its own field order, and
whether the next focusable widget is the next input.

Multiline keeps `newline`; a Return there inserts a line and the keyboard is
dismissed from the toolbar instead.
@coderabbitai

coderabbitai Bot commented Aug 20, 2026

Copy link
Copy Markdown

Warning

Review limit reached

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

Next review available in: 46 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: dc6c1c44-2b6e-482c-93e5-5b6ae6d20886

📥 Commits

Reviewing files that changed from the base of the PR and between f5fc620 and 843b5f8.

📒 Files selected for processing (5)
  • CHANGELOG.md
  • doc/widgets/w-input.md
  • lib/src/widgets/w_input.dart
  • skills/wind-ui/references/forms.md
  • test/widgets/w_input_test.dart

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!

The old default was undocumented, so the change had nothing to contradict,
which is its own problem: a reader had no way to know what the Return key
would do before running the app. `doc/widgets/w-input.md` now states the
resolved default in the props table and explains under Event Handling why
`.next` is an opt-in rather than a default.

The skill's forms reference gained section 10, since composing a form is
exactly when an agent decides this and it had no guidance at all. It points
at WKeyboardActions for the case where the advance order is not a clean run
of adjacent fields.

Skill version 2.12.0.
@anilcancakir

Copy link
Copy Markdown
Collaborator Author

@kodizm

1 similar comment
@anilcancakir

Copy link
Copy Markdown
Collaborator Author

@kodizm

@anilcancakir

Copy link
Copy Markdown
Collaborator Author

@kodizm

1 similar comment
@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.

A three-line default flip that is correct, tested both ways, and synced across the four surfaces it touches - nothing blocking.

Minor

lib/src/dynamic/w_dynamic_renderer.dart:379 — maintainability: _buildWInput never forwards textInputAction, so a JSON-driven form is the one caller that cannot state its own intent. Before this change it got .next implicitly; now it gets .done with no way back. Not introduced here and not worth blocking on, but the escape hatch this PR leans on ("only the form knows its own field order") is missing on that path, so WDynamic forms have no route to field-to-field advance short of WKeyboardActions.

lib/src/widgets/w_select.dart:810 — behavioural note, not a defect: WSelect's internal search field is a WInput with no textInputAction, so it silently moves from .next to .done. That reads as an improvement (Return no longer walks focus around inside the overlay), but if you want the key labelled correctly, TextInputAction.search is the honest value there. No changelog implication either way.

Correctness spot-checks that came back clean

  • maxLines is already forced to 1 for every non-multiline type (w_input.dart:469), so type == InputType.multiline is the same partition the widget uses everywhere else - no case where a maxLines: 5 text field gets .done on a genuinely multiline box.
  • onSubmitted fires on .done exactly as it did on .next, so submit-on-Return flows are untouched.
  • No other doc or skill page stated the old default; doc/widgets/w-form-input.md and skills/wind-ui/references/widgets.md only print the constructor signature, so nothing is left stale.
  • ### Changed over ### Fixed is the right call for a public default flip, and the BREAKING (behavioural) prefix plus the one-line path back are what a consumer reading release notes needs.

Tests

Both directions are pinned: the default now asserts .done (w_input_test.dart:466) and a companion asserts an explicit .next still reaches EditableText (:478), which is the assertion that stops the default being hardcoded past the parameter. The multiline .newline default keeps its own test at :490.

Checks I ran

  • flutter test test/widgets/w_input_test.dart test/widgets/w_form_input_test.dart test/widgets/w_select_test.dart+169: All tests passed!
  • dart analyze lib/src/widgets/w_input.dart test/widgets/w_input_test.dartNo issues found!
  • python3 tool/check-docs.py72 doc pages + 3 linking files against 171 demo routes: 0 issue(s)
  • Did not run the full suite or ./tool/coverage.sh 90; the three files above are the ones this diff can affect, and coverage cannot move on a 3-line expression change with tests on both branches.

Resolves the CHANGELOG conflict: this branch opens a `### Changed` section
where master had grown a `### Fixed` one, both inserted at the same position.
Kept both, ordered Changed then Fixed per the subsection list in CLAUDE.md,
with 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 e586d0b into master Aug 21, 2026
13 checks passed
@anilcancakir
anilcancakir deleted the fix/single-line-return-dismisses branch August 21, 2026 11:26
@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