-
-
Notifications
You must be signed in to change notification settings - Fork 408
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Outlet Focusing #66
Outlet Focusing #66
Conversation
Absolutely 100% agree with this. I was tossing around the idea of creating an addon that handled this but this absolutely is a core feature. I love that ember is getting some A11Y support. :) 👍 |
I am strongly 👍 on the concept here, we should definitely bake something in for this. I am not sure that DOM focusing behavior belongs in the route (though that isn't super important for the larger purpose here). In the mockup gist, I like that the implementation is done in the |
This is an awesome basic utility.
This has been an issue and I would expect pushback. My intuition is the pushback has been against poor implementations. I really hope that we can get to a place where focus is handled dynamically and with courtesy so that application flows are expressed seamlessly in visual and aural modalities. Keep experimenting! |
From experience with liquid-fire, adding toplevel divs to people's outlets is fairly disruptive. Can we get a similar benefit by focusing the first DOM node found inside the outlet? In cases where the user has already provided a single topmost element we would find it and use it, otherwise we would at least place the focus at the start of the new content. |
Okay, so it sounds like we want to do this, as well as ship a default implementation. This is just a starting place, so much more we can do... :) Notes from in-person conversations at Wicked Good Ember:
@jessebeach I'm going to reach out to you on a different channel, I feel like we should probably have a conversation. :) Adding a to-do list to this RFC. |
I would be hesitant about that. It means you can't jump into an ember app and understand what If we can't establish one behavior that works for everyone, I would rather help organizations opt into stricter behaviors through something like custom template linting rules. |
When @ef4 makes a good point... :) And since you hook into That being said, my goal would be that (something like) this could be a breaking change in Ember 3.0, and exposed as a feature in the 2.x series via global configuration that also throws a deprecation when configured for non-wrapped outlets. Yes it would require a possibly non-mechanical upgrade, yes it requires a flag, but being inaccessible because you didn't change the way you did your So, with your feedback in mind, my proposal is to change the default expectation which skirts around your problem. For bonus points it makes liquid-fire a touch easier to integrate for most users as you'll get your child container by default. |
The scroll behavior can be caught and prevented for sighted users: http://jsbin.com/faxazedaci/edit?js,output However, the function that is called for this handler should probably also be exposed as a public API as it is variable which element is scrolling, and it's a common enough problem that we have a guide for it: Resetting scroll on route changes. I feel like the open questions are resolved at this point, final public API needs to be discussed by core team, and this RFC needs to be updated to reflect those opinions. Unsurprisingly, I volunteer to implement. :) |
Morphs are not a public API, so you will need to design an alternate API that does not expose them to application developers. |
@tomdale My goal was pretty simple, I wanted to provide a maximally flexible primitive for extensibility. I know for a fact that we can't anticipate every use case (especially for something as important as designing an aural experience with inconsistent user agents) and I wanted to expose the possibilities of the underlying platform as closely as possible. (Yes, I'm quoting dogma.) It's for that reason I selected pushing the Morph all the way into a user-facing API. Below you'll find an enumeration of everything I considered. Do you have additional proposals for focus behavior that don't expose the Morph and don't come with some of the drawbacks of the first two? I'd even be game for a layer of indirection (enter hook versus activate hook for example) which pushes the default API up the ladder of abstraction while still giving you the ability to monkeypatch your way to success. Declarative in TemplateIn this case you could allow a user to declare which element is to be focused inside of their templates. To do this well we would need to ensure that every possible permutation of template content has exactly one focus target. Benefits
Drawbacks
No ChoicesWe force all outlets to be wrapped in a div (either from Ember itself, or as the first node in your template to opt in), and that's what is focused. Benefits
Drawbacks
Exposing the MorphMoves the focusing logic out of declarative code and into imperative code with a reasonable default implementation so that most people never touch the Morph that gets passed in. Benefits
Drawbacks
|
I missed the obvious solution: allow a user to pass in a selector in public API space, create a private API space function that receives the morph, grabs the selector, and sets the focus. Will update the RFC to be a complete picture of my current proposal with hopes to move this RFC into an "active" state. |
@nathanhammond Nice, looking forward to it |
I've updated the RFC, please re-review. Major differences:
I expect the last of these four to be the most contentious item in the RFC (it's the only breaking change), but it guarantees so much better results for assistive tech users that anybody who is serious about accessibility should be doing it anyway. Making this change will make it very uncommon that overwriting the default gives assistive tech users a better experience and all Ember apps will benefit. (Or, phrasing differently, making this change means that by default assistive tech users will likely have the best experience possible on every Ember app they encounter.) |
Thanks for your work on this, @nathanhammond. Is this RFC languishing? I think it would be an important statement to make consideration of accessibility a central goal of Ember, above just making Ember-developed sites more accessible by default. |
Stepping into this conversation wearing my hat as owner of accessibility at LinkedIn (and a native screen reader user) to ask the community for its support in doing what is necessary to assist @nathanhammond to quickly move this RFC through your approval process because the issue it seeks to address currently represents an accessibility show-stopper for anyone, including us, who want to develop apps using Ember that can be used by everyone, including screen reader users. I am unsure how your approval process works. That said, if there are any remaining concerns, could these please be identified now so Nathan can address them? Otherwise, I am asking the community to see your way to approving this RFC without delay so that it can be implemented. Based on feedback at Wicked Good Ember, I was pleased at the overwelming desire to make Ember-built apps accessible. Getting this critical issue resolved will go a long way in demonstrating this aspiration. @tomdale @wycats @rwjblue |
This is a thorny problem due to how apparently terrible screen readers are at reacting to DOM mutation. I am hesitant to make architectural changes -- especially ones with cost to the existing user base, like deprecating non-wrapped outlets -- that are based not on actual standards for accessibility, but on de-facto accessibility tricks that could break tomorrow, as browsers and screen readers change. The solution is also very incomplete, given how many other ways an Ember app will choose to mutate DOM: {{#if myStuffIsStillLoading}}
Hang on
{{else}}
The stuff ....
{{/if}} That would get missed by the focusing solution. Another problem scenario is anyone with multiple outlets, or with a more 2.0-style component-plus-service architecture for a sidebar or topbar. Lots of critical content in an Ember app is going to change outside of outlets. That is an encouraged and supported way to do things. The W3C does have a standard that looks like it solves our problem. I realize that user agents have been slow to fully implement it, but we can actually help push them forward by building it into every Ember app by default. The more apps we ship that use |
I currently use |
As I understand the discussion, the focus management is being proposed to solve two use cases:
In the first case, the constrained flow case, focus management is absolutely necessary. It's jarring either not have the focused moved into the dialog or not have the focused returned to the source element that started the flow. But this issue can be narrowly constrained to dialog interactions, at least for the purpose of this problem. As long as the routing system supports the control, even if the controls are arcane, this behavior can be built into component libraries so that product devs dont' have to worry about the specifics; they just use the dialog component. For case 2, the loading of new content, I agree with @ef4 that |
I just recreated a demo like @nathanhammond's original from Wicked Good Ember and tried putting @Robdel12 Why do you think aria-live is a hack? It was literally created to solve this case: telling assistive technologies that a part of your page is dynamic. |
@ef4 is it possible to share a URL so that your demo can be tried with JAWS and NVDA as well? Following standards notwithstanding, what ever solution(s) is ultimately agreed on and moved forward with, it will need to stand the test of different screen reader+browser combinations. The reality, as much as some hate it is that the balance of average screen reader users use either IE or FF with JAWS, based on the WebAIM screen reader survey, which is all we have re data. This is certainly the case based on the LinkedIn members I have interacted with. I appreciate that this conversation is moving. |
@ef4 As a demo, it's illustrative. But just be wary of apps with lots of subtly changing nodes. The "time since" auto-updates are particularly nuisant. Your app ends up spewing endless "5 minutes ago...6 minutes ago" updates into the audio stream. We have a similar issue with a |
@ef4 Basically @jessebeach summed it up very well. Anytime a DOM node changes it's going to alert the screen reader and it will begin to read it off. For example if github used That's why I think it's a hack to throw |
Yes, we need to try to automatically balance "too quiet" vs "too loud". The present situation is too quiet. I think outlet focusing would still be too quiet, for the reasons in my earlier comment (too much real content will get missed if we only notify the user agent immediately at outlet transitions). I agree that putting Regarding poor browser support: somebody has to implement this stuff before it's well-supported, otherwise it will never be well-supported. If we're going to also add hacks for noncompliant browsers, that is cool with me, as long as we can keep them self-contained and only apply them when we detect one of those browsers. |
I will work with Nathan to get some demos up that people can look at in different browsers. |
Thank you everybody for your thoughts. I'm going to drop a few notes in this forum and then disappear into a back channel to work toward a solution with @ef4. Many of these things have already been said, but I'll try again in an attempt to distill them further. ReasoningOne of Ember's underlying principles with regards to URLs was "don't break the web." We've succeeded wildly with URL management to the point that everybody knocks off the Ember router. However, the default behavior in screen readers when you visit a new page on the web is that it starts reading from the top of the newly loaded page. We've broken the web for the portion of assistive tech users reliant upon this behavior. ProblemEmber's route transitions (equivalent to page transitions) don't trigger the reading behavior of loading a new page and, as a result, the application state changes upon clicking a SolutionThis solution is intentionally very narrowly scoped to address the one problem which Ember itself created by getting rid of full-page refreshes. Content on the page which dynamically updates being presented to users of assistive tech is an open and thorny problem. This RFC does not attempt to address that problem. I'm of the opinion that holding up a solution to a problem which we created while looking for a silver bullet to address all of dynamic content is over-engineering. That being said, a generic solution for notifying of specific dynamic content changes is one of the open research projects on my plate. It is separate from this behavior as identifying how and when to present dynamic page content updates is about designing an experience for users of assistive tech and is likely an application-level concern which framework code should simply support mechanisms to make it easy. (I'm calling it "stream hijacking," and the premise is double-binding a stream into an off-screen notification center which can be read top to bottom like a log.) Standards
Further, as described by multiple people above, In short, we can't rely on behavior provided by the standards when the standards are insufficiently expressive to accomplish our goals. Insufficient standards are why we write SCSS and ES6 and have transpilers. It's why we write the Extensible Web Manifesto. We need to approach accessibility in the same way (pragmatic, and without waiting on a slow standards process) so that we don't leave today's assistive tech users behind. |
Update: Implemented as an addon, ember-a11y. Thanks to everybody here and @binhums for helping bring that home. It's not perfect (yet), uses @ef4's I'm closing this PR as a "wontfix." As |
👏 Thanks for the update @nathanhammond! When we next revisit outlets (around routable components) we should remember to consider these use-cases. |
Rendered
Research:
Implementation:
focus
hook.