Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Drawer jitters on open when input has autofocus #693

Closed
nadenf opened this issue Feb 21, 2022 · 11 comments
Closed

Drawer jitters on open when input has autofocus #693

nadenf opened this issue Feb 21, 2022 · 11 comments
Assignees
Labels
bug Things that aren't working right in the library.

Comments

@nadenf
Copy link

nadenf commented Feb 21, 2022

Describe the bug

When a Drawer contains an input field with autofocus enabled then it will jitter on first open with Safari.

This could have been fixed with the animation frame but wanted to raise in case.

To Reproduce

Steps to reproduce the behavior:

  1. Restart browser
  2. Visit here
  3. Click on Open Drawer button
  4. See error

Screenshots

Screen.Recording.2022-02-22.at.7.55.11.am.mov

Browser / OS

  • OS: Mac
  • Browser: Safari
  • Browser version: Version 15.3 (17612.4.9.1.8)
@nadenf nadenf added the bug Things that aren't working right in the library. label Feb 21, 2022
@claviska
Copy link
Member

It looks like this is happening due to Safari’s lack of support for preventScroll. This check appears to no longer work for some reason:

https://github.com/shoelace-style/shoelace/blob/next/src/internal/support.ts

I remember very specifically when this piece of code was added and it definitely was working. The reason it exists is so Shoelace can handle initial focus differently for Safari to prevent this exact problem.

Perhaps the check is broken now because Safari added experimental support for this (I’m speculating, but I recall seeing a WebKit email about the feature recently so it wouldn’t surprise me.)

This issue will go away on its own once Safari ships it, but until then we need a reliable check to work around it. I’ll see what I can come up with to feature detect preventScroll in a different way.

@nadenf
Copy link
Author

nadenf commented Feb 24, 2022

There is a mention of this issue in this bug:

https://bugs.webkit.org/show_bug.cgi?id=236584

@claviska
Copy link
Member

I can repro this in current, but it looks like it's working properly in next. Can you verify this for me in Safari?

https://next.shoelace.style/components/drawer?id=customizing-initial-focus

I believe 946fcf2 resolved it.

@nadenf
Copy link
Author

nadenf commented Feb 25, 2022

@claviska .. Tried this with my own project (using next) and it's still an issue with multiple different drawers.

I am asynchronously rendering this using React so I wonder if there is again some timing issue ?

@claviska
Copy link
Member

Can you post a repro?

@nadenf
Copy link
Author

nadenf commented Feb 26, 2022

I am using it with React + Scala.js so it's going to be a bit difficult to get a reproducible test case that makes sense.

I have noticed that it only happens when:

  1. Autofocus is enabled on an input field.
  2. Drawer is opened for the first time. Subsequent times there is no issue.

I have my project running with a local version of Shoelace. Is there anything I can add to drawer.ts to aid debugging ?

@nadenf
Copy link
Author

nadenf commented Feb 26, 2022

@claviska .. So have managed to track something down.

If I disabled setInitialFocus within drawer.ts I noticed that the issue still appeared.
And that's because the issue is with the input autofocus attribute which you are still setting for any input.ts within the drawer.

If I removed the attribute from input.ts and let drawer.ts set the focus the issue was fixed.

So would a fix be to remove the autofocus attributes from all focusable elements within drawer when it is first created ?

@claviska
Copy link
Member

If you remove autofocus from your inputs and use the old method of listening for sl-initial-focus and manually call el.focus({ preventScroll: true }), does the issue persist?

I suspect it will not, and in that case I think it's worth making a minimal repro and filing a WebKit bug as requested here to call out the problem of autofocus + animations.

Unfortunately, this is likely more of a Safari bug and if I can't feature detect it, I can't work around it.

@nadenf
Copy link
Author

nadenf commented Feb 26, 2022

This looks similar to this as well: microsoft/reactxp#526

@nadenf
Copy link
Author

nadenf commented Feb 26, 2022

I have a workaround if you're interested. And it does make sense that you would want to disable the HTML Input autofocus behaviour when you're going to be doing it yourself.

  async show() {
    if (this.open) {
      return undefined;
    }

    this.open = true;

    const target = this.querySelector('[autofocus]');
    if (target) {
      target.removeAttribute("autofocus");
      target.setAttribute("initial-focus", "true");
    }

    return waitForEvent(this, 'sl-after-show');
  }

  private setInitialFocus() {
    const target = this.querySelector('[initial-focus]');

    if (target) {
      (target as HTMLElement).focus({ preventScroll: true });
    } else {
      this.panel.focus({ preventScroll: true });
    }
  }

@claviska
Copy link
Member

claviska commented Feb 27, 2022

It was easier to work around this than try to reduce it and file a Safari bug. The solution I used was similar to your suggestion. I'm removing autofocus before the animation starts and adding it back after focus has been provided.

Safari seems to be honoring { preventScroll } so calling it manually instead of relying on its autofocus behaviour seems to solve it. (I believe this was happening because Safari calls focus() internally without { preventScroll: true } on the autofocused element.)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Things that aren't working right in the library.
Projects
None yet
Development

No branches or pull requests

2 participants