EmilTholin / svelte-routing

A declarative Svelte routing library with SSR support
MIT License
2.02k stars 178 forks source link

Reset focus after navigation #25

Open danielnixon opened 5 years ago

danielnixon commented 5 years ago

Please reset focus after page navigation. See the following for some resources on the topic:

EmilTholin commented 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.

hidde commented 4 years ago

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

hidde commented 4 years ago

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.

danielnixon commented 4 years ago

In case they're useful, here are parallel conversations happening in Vue and React land:

SteveALee commented 4 years ago

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.

danielnixon commented 4 years ago

@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.

mefechoel commented 4 years ago

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.