Skip to content

Commit ee49824

Browse files
authored
fix(input): clear button can be navigated using screen reader (#29366)
Issue number: resolves #29358 --------- <!-- 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. --> When the clear button is focused, `focusin` is dispatched and bubbles up to the `ion-input`. Our [scroll assist utility listens for `focusin`](https://github.com/ionic-team/ionic-framework/blob/2fc81ddc9b35d6909fd4b585079aedabbd659233/core/src/utils/input-shims/hacks/scroll-assist.ts#L135) to adjust the scroll position. It also causes the input to be re-focused. As a result, when swiping to the clear button with a screen reader, focus will be forcibly moved back to the input. This means that users cannot swipe away from the input to the right when using a screen reader. ## What is the new behavior? <!-- Please describe the behavior or changes that are being added by this PR. --> - To fix this, I decided to have the `focusin` event from the clear button not bubble (as opposed to add a really specific workaround to the scroll assist utility). Adding `stopPropagation` was easy enough, but it turned out that the scroll assist listeners were all configured to listen during the capture phase instead of the bubble phase. As a result, `stopPropgation` had no effect because the scroll assist callback had already fired. To address this, I updated the listeners to listen during the bubbling phase instead of the capture phase. Based on my testing the capture phase was not required for scroll assist to work, so it appears safe to remove. ## Does this introduce a breaking change? - [ ] Yes - [x] No <!-- If this introduces a breaking change: 1. Describe the impact and migration path for existing applications below. 2. Update the BREAKING.md file with the breaking change. 3. Add "BREAKING CHANGE: [...]" to the commit description when merging. See https://github.com/ionic-team/ionic-framework/blob/main/docs/CONTRIBUTING.md#footer for more information. --> ## Other information <!-- Any other information that is important to this PR such as screenshots of how the component looks before and after the change. --> Dev build: `8.0.1-dev.11713535425.1a4afba3` Reviewers: Please test this on a physical iOS device and be sure to test the scroll assist behavior. There is a test at http://localhost:3333/src/utils/input-shims/hacks/test you can use.
1 parent 23321f7 commit ee49824

File tree

2 files changed

+14
-5
lines changed

2 files changed

+14
-5
lines changed

core/src/components/input/input.tsx

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -783,6 +783,15 @@ export class Input implements ComponentInterface {
783783
*/
784784
ev.preventDefault();
785785
}}
786+
onFocusin={(ev) => {
787+
/**
788+
* Prevent the focusin event from bubbling otherwise it will cause the focusin
789+
* event listener in scroll assist to fire. When this fires, focus will be moved
790+
* back to the input even if the clear button was never tapped. This poses issues
791+
* for screen readers as it means users would be unable to swipe past the clear button.
792+
*/
793+
ev.stopPropagation();
794+
}}
786795
onClick={this.clearTextInput}
787796
>
788797
<ion-icon aria-hidden="true" icon={mode === 'ios' ? closeCircle : closeSharp}></ion-icon>

core/src/utils/input-shims/hacks/scroll-assist.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,7 @@ export const enableScrollAssist = (
124124
const focusOut = () => {
125125
hasKeyboardBeenPresentedForTextField = false;
126126
win?.removeEventListener('ionKeyboardDidShow', keyboardShow);
127-
componentEl.removeEventListener('focusout', focusOut, true);
127+
componentEl.removeEventListener('focusout', focusOut);
128128
};
129129

130130
/**
@@ -155,15 +155,15 @@ export const enableScrollAssist = (
155155
);
156156

157157
win?.addEventListener('ionKeyboardDidShow', keyboardShow);
158-
componentEl.addEventListener('focusout', focusOut, true);
158+
componentEl.addEventListener('focusout', focusOut);
159159
};
160160

161-
componentEl.addEventListener('focusin', focusIn, true);
161+
componentEl.addEventListener('focusin', focusIn);
162162

163163
return () => {
164-
componentEl.removeEventListener('focusin', focusIn, true);
164+
componentEl.removeEventListener('focusin', focusIn);
165165
win?.removeEventListener('ionKeyboardDidShow', keyboardShow);
166-
componentEl.removeEventListener('focusout', focusOut, true);
166+
componentEl.removeEventListener('focusout', focusOut);
167167
};
168168
};
169169

0 commit comments

Comments
 (0)