shoelace: Handler violations when using SL with SvelteKit
Describe the bug
I’m running into handler violations where event handlers took too much time to return (for instance focusin of modals and drawers taking seconds to process).
To Reproduce I made repro repo available here https://github.com/brgrz/sl-bugs
Steps to reproduce the behavior:
- Clone the repo
- Run npm i
- Run npm run dev, it will run the SvelteKit app at http://localhost:3000
- Open Chrome + devtools, in Devtools->Console tab->select All issues (or Verbose)
- Open the app, click the Open drawer button
- Inside the drawer try clicking around on the whitespace, try clicking into the input and then onto the whitespace and so forth
- You should be seeing instances of
[Violation] 'focusin' handler took 6519msin the Console (while this happens, the app will freeze preventing you to click on anything else)
Expected behavior No freezes, no violations/timeouts
Desktop (please complete the following information):
- OS: Windows 10
- Browser Chrome, Edge, both latest BUT was unable to reproduce this in Firefox
About this issue
- Original URL
- State: closed
- Created 3 years ago
- Comments: 28 (25 by maintainers)
Turns out the logic here wasn’t needed since we’re also iterating over child elements. This was causing some unintended recursion where the same elements were returned over and over again.
I’ve verified the fix works for the use case above, as well as with additional nested elements. This fix will land in beta.45.
I was able to repro this outside of SvelteKit: https://jsfiddle.net/geoffrich/pub0orke/
I reduced the example a bit, but the key difference is one line:
document.body.tabIndex = -1. SvelteKit sets tabIndex on the body so it can reset focus on client-side navigation. This repros the issue in the JSFiddle you linked. Interestingly, this only happens in Chrome/Edge, not in Firefox (I’m on Windows).The issue is in these lines: https://github.com/shoelace-style/shoelace/blob/1c010ffe5adaf9c2ffda8b818ee45a4feb359132/src/internal/modal.ts#L36-L40
For whatever reason, when tabindex is set on the body and you click inside the panel but not on one of the nested inputs,
pathis equal to[body, html, document, window], which does not includethis.element. This causesgetTabbableElementsto be run. When asl-selectis also in the drawer, it finds ~68k elements, causing the page to hang.To make it easier to repro, I set a border on the tab panel. Clicking the white space inside the border in Chrome will cause the issue.
This is really a “perfect storm” issue, since the following need to be true: EDIT: not entirely accurate, see my next comment.