shepherd
shepherd copied to clipboard
Targeted input loses focus on android and ios devices
Hey, I am having a weird issue in mobile devices that I cannot figure out.
Basically I have one step that targets an input element, and it is expected that the user types something to proceed to the next step.
This works fine when trying on desktop, but on android or ios when I click the input element to start typing the input immediately loses focus. On android is very obvious that the keyboard shows for a little bit and disappears
Here's a simple codesanbox showing the issue: https://codesandbox.io/s/silly-ritchie-o0w88?file=/src/index.js
The issue doesn't appear in the browser's responsive mode, only in the actual devices.
One thing that I noticed is that If I remove the 'shepherd-element' element from the dom it works fine. Not sure if this indicates something relevant
Thanks
@alexd16 this sounds like an issue with focus
. We focus trap the input to the shepherd-element
, so hitting tab will cycle through all the things in the tooltip and not cycle out. I think if you show the step, then try to focus something outside the step, it might just be trapped to focusing in the step. We should definitely look into this more.
@rwwagner90 Tested a bit more in chrome desktop and It does seem that it's the resize the does it.
This is what I tried
- Focus input
- Resize window
- input is not focused
- click next
- Focus input
- Resize window
- Input is focused
It doesn't really matter on chrome desktop because we don't usually resize the window, but the issue seems to match what's happening in android devices
Looking at this SO issue https://stackoverflow.com/questions/14854359/android-html-input-loses-focus-when-soft-keyboard-opens-asp-net, the first answer mentions that the keyboard opening on android does trigger a resize
Not sure if this helps, but I thought it was worth it to point out
@alexd16 ah, that is helpful info. We reposition things on resize and scroll I believe, so I could see that being a problem.
@rwwagner90 So I looked a bit in the codebase and I think I was able to find what is causing the issue. It's the focusAfterRender modifier that's set here: https://github.com/shipshapecode/shepherd/blob/master/src/js/utils/general.js#L110
It seems that it runs every time there is a resize which causes the issue. If I remove that modifier it seems to work fine (at least on android, didn't have the chance to test on iphone)
Does this make sense?
@alexd16 yes, that makes sense, however we need this modifier, so we shouldn't remove it. I think perhaps the fix would be to manually call .focus
on your element you want to focus, after Shepherd calls focus.
I suppose we could also try to make it not refocus after every resize, and just do it the first time. I am unsure of the best fix here.
@rwwagner90 yup, I figured we couldn't just remove the modifier. But this is pretty limiting in mobile right now, it's basically prevents any step to have any sort of input.
I think calling focus on the input after shepherd calls focus could lead to an infinite loop of the keyboard opening and closing (didn't test this).
I am not 100% sure what is the purpose of that modifier but from what I saw is for accessibility purposes right? What if shepherd calls focus only if the document.activeElement is not a form element (I am assuming document.activeElement is reliable, didn't test this)
@alexd16 we have to call focus on each step. It is for a11y. What we don't necessarily need to do is call it on every resize. I'm open to suggestions to fix it.
My assumption is that the resize logic is being triggered by popper so its outside of shepherd control. Let me know if this is a correct assumption This means we would need to remove the focus logic from the modifier and move it elsewhere.
Can't we do it inside the step's show method? It would meet the requirement of doing it on each step right? From what I can see it already has logic to handle the step's scrollTo option, I assume it could have the focus logic as well
Let me know what you think
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.
@alexd16 that seems logical. I'm unsure if we would hit timing issues with Popper or not.
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.
@xiwcx any interest in working on this?
apowerful1 has contributed $50.00 to this issue on Rysolv.
The total bounty is now $50.00. Solve this issue on Rysolv to earn this bounty.
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.
Hello, I am interested in working on this. Please do not close this issue due to staleness.
@rwwagner90 So I looked a bit in the codebase and I think I was able to find what is causing the issue. It's the focusAfterRender modifier that's set here: https://github.com/shipshapecode/shepherd/blob/master/src/js/utils/general.js#L110
It seems that it runs every time there is a resize which causes the issue. If I remove that modifier it seems to work fine (at least on android, didn't have the chance to test on iphone)
Does this make sense?
Disabling "focusAfterRender" from "popperOptions" in "defaultStepOptions" seems working for me.
var startTour = new Shepherd.Tour({ defaultStepOptions: { classes: 'shadow-md bg-purple-dark', scrollTo: false, cancelIcon: { enabled: true }, popperOptions: { modifiers: [{ name: "focusAfterRender", enabled: false }] } }, useModalOverlay: true });
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.
@ColinSather are you still interested in taking a look?
@alperenersoy yeah, we do need to keep it enabled though, as we need to focus the popper when it is rendered. See the discussion above.
Even if I disable focus using popperOptions
, I cannot see the input because it is covered by the popover. The keyboard does not close but I cannot see the input.
Maybe it should be possible to allow the popover to be out of the screen while an input is focused
Even if I disable focus using
popperOptions
, I cannot see the input because it is covered by the popover. The keyboard does not close but I cannot see the input.Maybe it should be possible to allow the popover to be out of the screen while an input is focused
You can try to hide "shepherd-element" class on focus and show it on focusout if it is not important to keep it open while typing. You should also check the element and position in attachTo property of steps. If you give more information about your using we can better help you.
@alperenersoy I finally made a workaround using a modal for that step in mobile, but I think that this should be considered when fixing this issue. If I have some time to try your solution I'll share the result here.
@andresespinosapc could you not use step.hide
and step.show
for this?
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.
Are there any plans to address this issue or has a suitable work around been found? This makes any form input on mobile impossible.
I'm having the same issue, is there a solution to this? Thanks!
We're certainly open to PRs to fix the issue, if anyone has any ideas!
I'm unable to replicate this issue currently. I have an Iphone 12 and M1pro macbook, no immediate access to an Android device to test on. I ended up pulling out my old Iphone SE running on iOS 14.2 and also could not replicate this issue.
I'm wondering if the latest iOS has resolved this type resizing issue. I don't see any changes in Popper.js git history that would lead to a resolution.
Seems like we should connect with an Android phone owner to test this and if its not an issue for them either, get this closed up. Thoughts?
@EmNicholson93 sounds good to me. @ktranel @CharlotteArai @andresespinosapc @alperenersoy can any of you confirm if this issue is gone as of Shepherd 10.0.1 please?
@rwwagner90 Just stumbled on this thread by accident since I had exactly this issue (focusing an input makes it lose it immediately). The device is a Google Pixel 5, Shepherd is on version 10.0.1. For me the fix with the popperOptions given above is working fine, but since you just talked about if it is still happening on Android - it seems it is.
I just hit this issue on PC as well. Iam using Vue-Multiselect and when menu with options is open it does resize slightly parent modal dialog. As i need to guide user to fill data into this dialog its content is target for step as whole. So user clicks into input to choose from selectbox, this triggeres resize and shapperd in change forces focus on itself as part of computePosition
near // Replaces focusAfterRender modifier.
It seems there is no way of blocking this force focusing. Maybe simple option for disabling autofocus after repositioning? Seems like simple fix. Over all iam not sure i understand well why its even ther in first place. Seems that focus is good when step is opened for the first time but after that it feels like bug