Open danielnixon opened 5 years ago
I saw this interesting tweet thread by Ryan Florence, and we could possibly implement something similar in svelte-routing
. Maybe an action focus
that can be used on an element in a Route
component so that element is focused when the Route
is created?
It's possible to do a very naive focus reset today with pure Svelte:
<!-- MyRouteComponent.svelte -->
<script>
import { onMount } from 'svelte';
let domNode;
onMount(() => {
domNode.focus();
});
</script>
<input bind:this={domNode} />
The new focus
action could do this, but also take all the special cases Florence mentions into account.
Focus behavior that isn't completely resetting (non ideal, but workable), is tricky.
Would it be useful to do this in two stages? I mean, first reset focus on route, and then second work on something that gives developers more control over where focus should go, so that they can do it intentionally?
If so I'm happy to try and submit a PR for this!
Related: Marcy Sutton from Gatsby did a number of user tests with client side routing in June, see What we learned from user testing of accessible client-side routing techniques with Fable Tech Labs | GatsbyJS
I've submitted https://github.com/EmilTholin/svelte-routing/pull/95 to reset focus after routing.
In the meantime, the Gatsby folks worked on https://github.com/gatsbyjs/gatsby/pull/19290, which has a mechanism that announces routes to screenreader users with a specific announcement component (which really just is an element with some ARIA attributes and relevant content, the announcement itself is done by browser/AT). The “relevant content“ is either page title or first h1
in route content.
@EmilTholin would you consider a PR that introduces such a route announcement component? I think it would make svelte-routing
a much better choice for developers who prioritise accessibility.
In case they're useful, here are parallel conversations happening in Vue and React land:
In order to better reproduce browser behaviour on a page refresh perhaps we should also search for the autofocus
attribute? Not sure what the expected behaviour is if there is more than one set.
Also there is pesky iOS safari not implementing autofocus
which makes it hard to use, even though it can be useful.
@SteveALee I would tread very carefully with autofocus
. See e.g. https://webaim.org/blog/future-web-accessibility-html5-input-extensions/
ETA:
Back in the dark ages of server-rendered apps, it would have been possible for a user agent to ignore the autofocus
attr that arrives in the html response from the server, and for it to do this for all sites per a user setting (e.g. in Firefox this is the browser.autofocus
setting).
When it comes to SPAs (putting SSR aside for a moment) the SPA framework would have to emulate the Browser's native autofocus
behaviour via JavaScript. The depressing pattern seems to be that (re)implementing the Browser's native behaviour is always done badly† and autofocus
would be no different. The SPA's emulated autofocus
behaviour would have to render the view into the DOM, notice the autofocus
attr and then adjust focus via a JavaScript DOM call to element.focus()
. Notably, it would have no way of tapping into user agent preference to ignore autofocus (there's no standard API for this) which means it would no longer be possible for the user to disable autofocus behaviour via a browser setting.
You could perhaps imagine some standard or quasi-standard way to expose this setting (perhaps a la prefers-reduced-motion
media query) but I'm not aware of anything in this direction.
† Announcing page load, focus management, restoring scroll position on back button, etc are mostly ignored by SPA authors.
I have implemented focus management in svelte-navigator (see Router.svelte, Route.svelte and a11y.js), which is based on svelte-routing. I'm sure there is a lot that could be improved, but maybe there is something in there that could help get things started.
Please reset focus after page navigation. See the following for some resources on the topic: