Skip to content

fix: resolve keyboard issue in modal bottom sheet on iOS and update v… - #651

Open
stelselim wants to merge 4 commits into
mx/11.12.xfrom
moo/2480/fix-keyboard-issue-11-12
Open

stelselim wants to merge 4 commits into
mx/11.12.xfrom
moo/2480/fix-keyboard-issue-11-12

Conversation

@stelselim

@stelselim stelselim commented Sep 22, 2026 •

Copy link
Copy Markdown
Contributor

No description provided.

@stelselim
stelselim requested a review from a team as a code owner September 22, 2026 08:05
stelselim and others added 3 commits September 23, 2026 10:57
A sheet too tall to fit above the keyboard is pinned to the top of the
container with its content area shrunk, leaving inputs further down behind
the keyboard. SheetKeyboardTracker now scrolls the focused input into that
area on keyboardDidShow, and again once the sheet's resize spring has
settled, since the first scroll is clamped to the content area as it was
mid-animation.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The keyboard fix only covered the custom modal sheet. The expanding drawer
renders the same page content, so an input inside it was still covered.

Two things had to be generalised first:

- The scroll correction assumed the scrollable starts at the top of the
  screen, which only holds for a sheet that fills a modal. RN compares the
  input's offset within the scroll content against the keyboard's position
  on screen, so the scrollable's own distance from the top is now measured
  and added to the requested offset. No change for the modal sheet, where
  that distance is zero.
- A drawer shares the screen with the page, so "iOS only raises the keyboard
  for a first responder, and the sheet fills a modal" no longer proves the
  keyboard is the sheet's own. The drawer claims a keyboard only once the
  focused input has been measured against its scrollable, and releases the
  claim when the keyboard hides, so an input elsewhere on the page leaves it
  alone. The claim happens on keyboardDidShow, the earliest point where RN
  has recorded the focused input, which costs the drawer the in-sync rise
  that the modal sheet gets from keyboardWillShow.

The basic modal is left alone: its items are captions with an action, so
nothing inside it can take focus.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
`keyboardBlurBehavior: "restore"` returns the sheet to the snap point it is
recorded at when the keyboard hides. That index is only updated once an
animation completes, so a keyboard hiding mid-close restores the sheet to the
position it was closing from, cancelling the close. The replacement animation
ends on the index the sheet already had, so neither onChange nor onClose
follows and nothing retries: the sheet stays open while the trigger attribute
reads false. The library guards its own pan-down-to-close against this, but
not a programmatic close.

The modal sheet now dismisses with `forceClose`, which blocks every position
change that does not come from the user until the sheet is closed, and takes
an open keyboard down with it.

The expanding drawer has no close path, but it has the same problem in a
different shape: collapsing it by a drag leaves an input inside it focused,
with the keyboard covering what is left of the drawer. It now dismisses that
keyboard on collapse -- only when the focused input is its own, since its
snap points are derived from measured content and it can snap without the
user, which must not take the page's keyboard down with it.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants