sveltejs / sapper

The next small thing in web development, powered by Svelte
https://sapper.svelte.dev
MIT License
6.99k stars 433 forks source link

Focus is not reset to top of DOM on route change #1083

Open davidluhr opened 4 years ago

davidluhr commented 4 years ago

Describe the bug Current, route changes leave keyboard focus in the same position in the DOM and do not announce a new page has loaded.

I see issue #287 was closed, and was happy to see @Rich-Harris bring this up, but it doesn't seem to have been implemented. My apologies if I'm missing something, but my own testing shows this issue still exists.

To Reproduce

  1. Use a screen reader (VoiceOver, NVDA, etc.)
  2. In any Sapper project with more than one route, navigate to a link that points to another route
  3. Activate the link
  4. Observe the screen reader does not announce anything, and keyboard focus remains in the position in the DOM.

Expected behavior For accessibility, focus should be reset to the top of the DOM on route change and match native browser behavior when navigating to a new URL. Natively, a new URL will announce the new <title> to assistive technology and focus will begin at the top of the DOM so users can navigate through the new page.

Without this functionality, there's no way for screen reader users to know the route changed, or to know where keyboard focus is in the DOM.

Severity I view this as a critical bug. This has prevented me from using Sapper for my projects, because I cannot exclude many users from being able to use the website. Users who rely on assistive technologies constitute a sizeable global population, and Sapper has an opportunity to lead the way in creating an accessible SPA-like experience that front-end frameworks are lacking.

alekpentchev commented 4 years ago

On Mac after launching VoiceOver I've created a simple app (based on the template from Sapper's docs) with basic routing. When navigating from Page1 to Page2 focus changes to the top of the page and the keyboard focus (black rectangle) remains where it was before. But after tapping tab, keyboard focus seems to focus on the next element from the top not where the navigation happened from. So it looks like it works correctly. Did I understand your intention correctly, @davidluhr ?

davidluhr commented 4 years ago

To help clarify, here's a screen capture of the current behavior in Sapper: User has keyboard focus on about link, tabs to blog link, clicks blog link, and focus is not reset nor is new URL announced

In this recording, I'm using the default Sapper starter template. I am using VoiceOver, and have keyboard focus on the "about" page link. I tab to the "blog" link, activate it, and the route changes to the blog page. However, VoiceOver does not announce this new page in any way, and keyboard focus remains on the blog link.

For users who rely on assistive technology, they may not know that the page has changed. Normal URL changes in the browser will be announced by screen readers by declaring the new page's <title>, and keyboard focus will be reset to the top of the DOM. In Sapper, this announcement doesn't happen, and users might be confused or lost. Additionally, because focus is not reset to the top of the DOM, it may be difficult to navigate a new page as expected.

The Gatsby team has been researching this and recently published a post with their idea for more accessible client-side routing. This solution uses an aria-live region that announces the page <title> on route change, and they also make sure keyboard focus is reset to the top of the page. This is just one approach, but hopefully the Sapper team has ideas of how to replicate functionality that matches a normal URL change in the browser.

Let me know if you have any questions about this. Thanks for your thoughts and help!