Skip to content

fix: keyboard and input bugs found by replaying other libraries' issues - #55

Merged
ronickg merged 1 commit into
mainfrom
fix/keyboard-issue-sweep
Sep 28, 2026
Merged

ronickg merged 1 commit into
mainfrom
fix/keyboard-issue-sweep

Conversation

@ronickg

@ronickg ronickg commented Sep 28, 2026

Copy link
Copy Markdown
Owner

Bugs found by integrating 0.3.3 into Uno and by replaying reproductions from open issues in keyboard-controller, react-native, react-native-screens and react-navigation. Patch release material (0.3.4).

Fixes

iOS: focused field that takes no typing (keyboard-controller#1588)

  • keyboard-controller wraps the focused field's delegate in one composite shared by every input. When focus moves faster than it re-wraps, it forwards one field's delegate calls to another field.
  • Seen in Uno: pushing a screen with an autoFocus field while a number field had the keyboard. Keystrokes went to the number field, which dropped the letters.
  • NitroInput now sends a delegate call for another field to that field's own view, and puts its own delegate back before it starts editing.
  • Either fix alone cleared the repro in 3 of 3 runs.

focus() at mount opens the keyboard even when it is down (both platforms)

  • A focus() that arrived before the view was on screen was only honoured while the keyboard was up.
  • That dropped the effect-focus of a free-text question shown after a tap-only one (Uno's questionnaire).
  • A view that has never been on screen now takes the focus, as autoFocus does. Screens navigated back to keep the old rule.

iOS: autoFocus on a push with no slide (react-navigation#11643, #11626)

  • Applies to animation: 'none', 'fade' and 'simple_push'.
  • UINavigationController ended editing in the incoming view mid-transition, then gave first responder back as the transition completed. The result was an onBlur/onFocus pair and a keyboard dip.
  • The field now declines that resign until the transition ends. blur(), another field claiming focus, the handoff stand-in and leaving the window still resign it.

iOS: selection set while blurred is applied on focus (RN#46943).

iOS: IME composition (Japanese, Chinese, Korean) with maxLength or transform (RN#56463, #52552)

  • The marked text is left to the IME, and a controlled echo mid-composition is skipped.
  • maxLength and the transform apply once the text is committed.
  • Checked on the simulator with the Japanese keyboard: composition runs past the limit and is cut to maxLength on commit.

Android

  • maxLength counts code points when typing (CodePointLengthFilter). LengthFilter counted UTF-16 units, so an emoji took two places.
  • Keyboard prop changes on a focused field keep the caret; setInputType reset it to 0 (RN#38676).

Tests

New example/__tests__/nitro-input-issues.harness.tsx replays 23 issue reproductions:

  • Navigation: autoFocus across animation values; a push with the keyboard down; formSheet; action sheet after blur or unmount; pop with a field on the covered screen.
  • Focus: blur or dismiss while the keyboard opens; autoFocus with no blur after; blur with another field on screen.
  • Text and selection: no spurious onChangeText; maxLength on programmatic values, huge values and emoji; lone surrogates; value and selection set together; selection set before focus; re-setting text after a clear; prop changes while focused; selectTextOnFocus; fast mount/focus/unmount churn.

The keyboard suite gains a focus-from-effect test.

  • bun run test:harness:ios (iPhone 17 simulator): 118/118
  • bun run test:harness:android-device (Galaxy A22): 116/116; the two action-sheet tests are iOS-only
  • bun run typecheck
  • Uno (iPhone 17 simulator, Galaxy A22): the transfer amount → pushed field repro, the questionnaire memo question, and the email → code view switch

🤖 Generated with Claude Code

- iOS: route delegate calls misdirected by keyboard-controller's shared
  composite delegate to the field they belong to, and reclaim the field's
  own delegate before editing (keyboard-controller#1588): a focused field
  took no typing after a push.
- focus() before the view is ever on screen is taken whatever the keyboard
  is doing, like autoFocus (a free-text step after a tap-only one never
  opened the keyboard). Both platforms.
- iOS: an autoFocus field on a screen pushed without a slide keeps its
  focus through the transition: no onBlur/onFocus pair and no keyboard dip
  (react-navigation#11643, #11626).
- iOS: a selection set while blurred is applied on focus (RN#46943).
- iOS: IME compositions (Japanese, Chinese, Korean) are left alone with
  maxLength or a transform, and conformed once committed (RN#56463, #52552).
- Android: maxLength counts code points when typing; keyboard prop changes
  on a focused field keep the caret (RN#38676).
- New harness suite replaying 23 issue reproductions; a mount-focus test
  in the keyboard suite.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@ronickg
ronickg merged commit 85f695e into main Sep 28, 2026
5 of 6 checks passed
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