Repository navigation
perf(mobile): debounce keyboard inset writes, fast-path focusout - #239
Merged
Merged
Conversation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
installKeyboardInsetwrote--kb-inseton everyvisualViewportresize/scrollevent. During the keyboard open/close animation the viewport fires nearly every frame, so each frame forced a full style recalculation on the root element and a re-layout ofAppShell— competing with the dialog / expand animations running at the same time and causing dropped frames. On the way back up, the inset also stayed stale until the keyboard animation finished, so the layout returned to full height late.Changes
packages/mobile/src/keyboard-inset.tsresize/scrollnow schedule a write that only fires after the viewport has been quiet forKEYBOARD_SETTLE_MS(120 ms), so the animation produces a single jump instead of one write per frame.currentcache skipssetPropertywhen the value is unchanged.focusoutfast path. When focus leaves a keyboard-capable element and does not land on another one, the keyboard is definitely closing, so the inset is written to0immediately — dialogs opening or tasks collapsing no longer wait for the keyboard animation to finish. Window blur (!document.hasFocus()) is ignored, since focusout also fires when the app is backgrounded and the keyboard may still be up.isKeyboardTarget()helper. Classifiestextarea,contenteditable, and text-likeinputs as keyboard targets, excluding non-text input types (button,checkbox,radio,range,file,color, etc.).focusoutlistener is removed and the pending timer cleared in the returned cleanup function.packages/ui/src/components/common/FieldPicker.tsxtransition-[top,max-height]to the dialog card so it glides to the new centred position when--kb-insetjumps once at the end of the animation, instead of tracking the keyboard frame by frame.Tests
packages/mobile/src/keyboard-inset.test.tsnow uses fake timers and a sharedvisualViewportstub, and covers:KEYBOARD_SETTLE_MSelapses, then a single write;scrollgoing through the same debounced path;focusoutcaused by window blur;isKeyboardTargetfor text inputs,textarea,contenteditable, buttons, checkboxes, andnull.