Closed Rich-Harris closed 3 years ago
(Not pictured: a solution to i18n, when constructing the Navigated to {title}
text)
closed via #309 and #311
For future consideration (haven't really thought this through): Could this be a component that can be imported via $app/a11y
or something? People could then use it in their layout like this:
<script>
import Announcer from "...";
</script>
<Announcer let:title>
Hey, I've navigated to {title}
</Announcer>
I like that solution, it's a good way to make it customisable without configitis. The trade-off is you're much likelier to omit (or duplicate!) it, would need to think about how to avoid that.
$app/a11y
could also be useful for things like skip nav links
On "how to avoid": I guess this is the tradeoff here. To diminish this, we could add it to the template that is bootstrapped when using create-svelte
.
Wanted to drop a note: the main application sveltekit app I'm working with uses a full-height, full-width css grid element as its primary "canvas", and the presence of a tabindex
on the body removes all keyboard-based scrolling behaviour (arrow keys, PgDn, etc.) that was previously working.
I'm using the following in our _layout.svelte
to counteract this for now, but it feels pretty hacky:
onMount(async () => {
document.body.removeAttribute('tabindex');
When using goto
there's now an option to not reset focus. The same doesn't exist as a directive for a
tags yet though
@dummdidumm I appreciate the option, but we would need this for effectively all routes throughout the app. I wonder if there's some way to do it at a global config level?
There's not right now, Rich mentions this in the initial post. I think it's best if you open a new feature request, outlining the current problem in detail as well as proposing some solutions, like the config option.
For future consideration (haven't really thought this through): Could this be a component that can be imported via
$app/a11y
or something? People could then use it in their layout like this:<script> import Announcer from "..."; </script> <Announcer let:title> Hey, I've navigated to {title} </Announcer>
I would like to second this. This is something which for example Drupal provides as well.
On a general note: I'm very happily surprised at the state of a11y support being provided by Svelte. Keep up the good work!
As an added suggestion: can we add an a11y tag to the issue tags? I'd be happy to help out where i can with anything a11y related. It's easier to search for those issues if there's a tag for it.
https://github.com/sveltejs/sapper/issues/1083, basically.
There are two separate issues to consider in order to make client-side routing accessible:
1. Managing focus
In a server-rendered app, any time you navigate to a page, the
<body>
is focused. In Sapper and SvelteKit apps, we blur the currentactiveElement
upon navigation, but this doesn't actually reset the focus, which is what we need — it just removes it temporarily. As soon as you press the tab key (or shift-tab), focus moves to the element after (or before) whichever element was focused prior to the navigation, assuming it still exists in the DOM. This is not desirable.Went down a bit of a rabbit hole trying to understand current recommendations:
<h1>
I'm sure there are other suggestions too. Each comes from an accessibility expert and has a solid argument, but ultimately they are mutually exclusive. Any would be better than the status quo though.
My inclination in the short term is to simply focus
<body>
(i.e. David Luhr's suggestion) — it's easy to implement, and matches the behaviour of server-rendered apps. In the future perhaps we could investigate alternatives, particularly ones that put power in app developers' hands rather than making one-size-fits-all decisions for them.The short term solution ought to be fairly straightforward — we just change this...
https://github.com/sveltejs/kit/blob/e09b6be95af81077e0fb0240ad94b1c0e41c9b3a/packages/kit/src/runtime/internal/router/index.js#L180-L182
...to this:
(Better still, only set the
tabindex
once, when the router initialises.)2. Announcing the page change
Per the recommendation in https://www.gatsbyjs.com/blog/2019-07-11-user-testing-accessible-client-routing/, we should add an ARIA live region that announces new pages. That looks something like this:
This could live inside the auto-generated
root.svelte
component.It makes sense for
title
to simply reflectdocument.title
, I think, rather than introducing some complicated way to customise it, since a page already needs an informational document title for SEO and accessibility purposes.