Closed dslatkin closed 6 months ago
Will this work? https://svelte-radix.codewithshin.com/#Unfocusable_icon
You can create a global custom icon. https://svelte-radix.codewithshin.com/#Setting_Global_Icon_using_setContext Or create a default icon, https://svelte-radix.codewithshin.com/#Creating_a_Default_Icon_Setting
That would "work" in the sense it is a workaround, but it doesn't feel good and I don't think it really addresses the root cause of having an unused event listener inadvertently make something focusable. Some of what's nice about using a library for icons is that one doesn't have to concern themselves with this kind of detail and wouldn't run into "gotchas", especially for things to do with focus handling. 🙁
While the tabindex="1"
solves the issue of being focusable via tab, I'm still experiencing other behavior due to these defaults:
https://github.com/shinokada/svelte-radix/assets/64506580/bf20b635-f037-4d4f-9c04-67556d552637
Of course this is possible to address by adding "outline: none" to every single icon, or I suppose defining the global icon.
Would it be possible to add a withEvents
prop to the icon that would take care of conditionally rendering it with events forwarded?
<script>
export let withEvents = false
// ... rest
</script>
{#if withEvents}
<svg on:focus on:blur on:whatever />
{:else}
<svg />
{/if}
I'd really like to continue using this project, so if you're open to the idea please let me know. If you're strapped for time and need a PR, a few of us are willing to assist!
If this isn't something you see yourself supporting, please let me know so I can determine how to proceed!
No problem. I can update it.
Hi @shinokada, I had a working prototype using the svelte-preprocess-delegate-events
library, so I polished it off and opened a PR with it. Feel free to use it or go a different direction of course, just submitting in case to save you some work if that's something you'd want. 🙂
Please try v1.1.0. I will update the docs later.
I close the issue for now. Thank you for your contribution.
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:
A bit more confusing, in
shadcn-svelte
you can see the issue created when the icon is used inside a button:<button>
and once for the<svg>
Additional Information
Why this is happening (I think):
In Svelte, if you add
on:focus
oron: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 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
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:
on:blur
andon:focus
event forwarding (a button or link containing the button should be used anyways for accessible interactivity)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.