[BUG]: Forwarding on:focus and on:blur events on the icons causes unpredictable focus behavior
bug
### Description of the bug
SVG icons are focusable by default in the library, contrary to their default behavior in HTML, which causes especially confusing behavior when using them inside other focusable elements such as `<a>` or `<button>` tags when using keyboard navigation or assistive technology.
This **only happens in Chrome** but not on Firefox or Safari (at least in my testing on Mac).
I originally reported this in huntabyte/shadcn-svelte#867.
Thank you! 🙏
### Steps To Reproduce
On the library's website:
1. Go to the [icon search page](https://svelte-radix.codewithshin.com/icons)
2. Type in "circle" into the search bar
3. <kbd>Tab</kbd> multiple times to see icons are focusable despite being non-interactive
A bit more confusing, in `shadcn-svelte` you can see the issue created when the icon is used inside a button:
1. Go to a component using an icon like [the calendar](https://shadcn-svelte.com/docs/components/calendar)
2. Click inside the box to bring focus close to the component
3. <kbd>Tab</kbd> through the interactive elements, notice focus needs to move through the previous/next month buttons twice, once for the `<button>` and once for the `<svg>`
4. Push <kbd>Space</kbd> or <kbd>Enter</kbd> to see that focus on the icon won't do anything
### Additional Information
Why this is happening (I think):
In Svelte, if you add `on:focus` or `on:blur` to an HTML element to forward events to parent components, it sets up an event listener even if no component listens for the event. Unfortunately, the SVG spec allows [focus-related listeners](https://svgwg.org/svg2-draft/single-page.html#interact-Focus) on SVGs to make the element focusable, but it's only an optional detail for rendering engines to implement. Blink (Chrome) implements it but Safari and Firefox do not.
Because of this, a situation like
```html
<button>
<Calendar />
</button>
```
is especially confusing for a user who is using keyboard navigation or assistive technology. They will have to tab/navigate _twice_ for each icon.
I think a couple solutions would be:
1. remove the `on:blur` and `on:focus` event forwarding (a button or link containing the button should be used anyways for accessible interactivity)
2. use a preprocessor library like [svelte-preprocess-delegate-events](https://github.com/baseballyama/svelte-preprocess-delegate-events) to forward all events without Svelte setting up listeners
I tested the second option and it seems to work without causing the same issue. I could open a PR but I think the first option would be simpler and encourage much better accessibility practices in general. 🙂 Svelte 5's new implementation will fix this in the future.
关闭于 2024-03-13 7 条评论