fix(scroll-assist): set correct scroll padding (#27261)

Issue number: resolves #27257

---------

<!-- Please refer to our contributing documentation for any questions on
submitting a pull request, or let us know here if you need any help:
https://ionicframework.com/docs/building/contributing -->

<!-- Some docs updates need to be made in the `ionic-docs` repo, in a
separate PR. See
https://github.com/ionic-team/ionic-framework/blob/main/.github/CONTRIBUTING.md#modifying-documentation
for details. -->

<!-- Please do not submit updates to dependencies unless it fixes an
issue. -->

<!-- Please try to limit your pull request to one type (bugfix, feature,
etc). Submit multiple pull requests if needed. -->

## What is the current behavior?
<!-- Please describe the current behavior that you are modifying. -->

1. Scroll assist was appending padding data every time it ran which
caused the amount of padding to infinitely grow until an input was
blurred
2. Calling `inputEl.focus()` caused scroll assist to run again which
caused unexpected scrolls

## What is the new behavior?
<!-- Please describe the behavior or changes that are being added by
this PR. -->

- `currentPadding` is either preserved or set, never incremented
- Added a special attribute to inputs that are manually focused so
scroll assist knows not to re-run

## Does this introduce a breaking change?

- [ ] Yes
- [x] No

<!-- If this introduces a breaking change, please describe the impact
and migration path for existing applications below. -->


## Other information

<!-- Any other information that is important to this PR such as
screenshots of how the component looks before and after the change. -->
This commit is contained in:
Liam DeBeasi
2023-04-26 10:50:26 -04:00
committed by GitHub
parent 65245826e3
commit 7e1f996dc6

View File

@ -9,6 +9,8 @@ import { setScrollPadding, setClearScrollPaddingListener } from './scroll-paddin
let currentPadding = 0;
const SKIP_SCROLL_ASSIST = 'data-ionic-skip-scroll-assist';
export const enableScrollAssist = (
componentEl: HTMLElement,
inputEl: HTMLInputElement | HTMLTextAreaElement,
@ -37,6 +39,16 @@ export const enableScrollAssist = (
* mobile Safari from adjusting the viewport.
*/
const focusIn = async () => {
/**
* Scroll assist should not run again
* on inputs that have been manually
* focused inside of the scroll assist
* implementation.
*/
if (inputEl.hasAttribute(SKIP_SCROLL_ASSIST)) {
inputEl.removeAttribute(SKIP_SCROLL_ASSIST);
return;
}
jsSetFocus(componentEl, inputEl, contentEl, footerEl, keyboardHeight, addScrollPadding, disableClonedInput);
};
componentEl.addEventListener('focusin', focusIn, true);
@ -46,6 +58,24 @@ export const enableScrollAssist = (
};
};
/**
* Use this function when you want to manually
* focus an input but not have scroll assist run again.
*/
const setManualFocus = (el: HTMLElement) => {
/**
* If element is already focused then
* a new focusin event will not be dispatched
* to remove the SKIL_SCROLL_ASSIST attribute.
*/
if (document.activeElement === el) {
return;
}
el.setAttribute(SKIP_SCROLL_ASSIST, 'true');
el.focus();
};
const jsSetFocus = async (
componentEl: HTMLElement,
inputEl: HTMLInputElement | HTMLTextAreaElement,
@ -63,7 +93,7 @@ const jsSetFocus = async (
if (contentEl && Math.abs(scrollData.scrollAmount) < 4) {
// the text input is in a safe position that doesn't
// require it to be scrolled into view, just set focus now
inputEl.focus();
setManualFocus(inputEl);
/**
* Even though the input does not need
@ -75,7 +105,6 @@ const jsSetFocus = async (
* see the page jump.
*/
if (enableScrollPadding && contentEl !== null) {
currentPadding += scrollData.scrollPadding;
setScrollPadding(contentEl, currentPadding);
setClearScrollPaddingListener(inputEl, contentEl, () => (currentPadding = 0));
}
@ -87,7 +116,7 @@ const jsSetFocus = async (
// doesn't freak out while it's trying to get the input in place
// at this point the native text input still does not have focus
relocateInput(componentEl, inputEl, true, scrollData.inputSafeY, disableClonedInput);
inputEl.focus();
setManualFocus(inputEl);
/**
* Relocating/Focusing input causes the
@ -103,7 +132,7 @@ const jsSetFocus = async (
* the keyboard.
*/
if (enableScrollPadding && contentEl) {
currentPadding += scrollData.scrollPadding;
currentPadding = scrollData.scrollPadding;
setScrollPadding(contentEl, currentPadding);
}
@ -128,7 +157,7 @@ const jsSetFocus = async (
relocateInput(componentEl, inputEl, false, scrollData.inputSafeY);
// ensure this is the focused input
inputEl.focus();
setManualFocus(inputEl);
/**
* When the input is about to be blurred