building for accessibility

49
Designing

Upload: nathan-hammond

Post on 12-Aug-2015

4.556 views

Category:

Technology


2 download

TRANSCRIPT

Page 1: Building for Accessibility

Designing

Page 2: Building for Accessibility

Is This Designing?

http://www.adobe.com/inspire/2013/11/photoshop-reflow-generator.html

Page 3: Building for Accessibility

Is This Designing?

https://flic.kr/p/qR7Lo8

Page 4: Building for Accessibility

Is This Designing?

http://thisoldcity.com/advocacy/photos-what-snow-tells-us-about-creating-better-public-spaces-e-passyunk-avenue

Page 5: Building for Accessibility

Is This Designing?

https://flic.kr/p/7bRxB2

Page 6: Building for Accessibility

Yes.

Page 8: Building for Accessibility

http://www.unicode.org/reports/tr51/tr51-2.html#Emoji_Modifiers

Page 9: Building for Accessibility

Good Design

https://flic.kr/p/die16e, https://flic.kr/p/99ad9q

Page 10: Building for Accessibility

Universal Design

Stokke Tripp Trapp

Page 11: Building for Accessibility

Universal?

Page 12: Building for Accessibility

Designing for Accessibility

Page 13: Building for Accessibility
Page 14: Building for Accessibility
Page 15: Building for Accessibility
Page 16: Building for Accessibility
Page 17: Building for Accessibility

http://www.istockphoto.com/photo/group-of-business-men-and-women-in-a-meeting-37790018

Page 18: Building for Accessibility

https://flic.kr/p/asasy3https://flic.kr/p/asasy3

Page 19: Building for Accessibility

https://commons.wikimedia.org/wiki/File:US_House_Committee.jpg

Page 20: Building for Accessibility

https://flic.kr/p/9ZA2Jx

Page 21: Building for Accessibility
Page 22: Building for Accessibility

Demo

Page 23: Building for Accessibility

Learnings• Screen readers start reading from the top of the

page on each page load.

• Dynamically updating the DOM results in no information being passed to the user by default.

• Markup is still important. Ember's real links and the code you write in your templates is important.

• ARIA roles still do what we expect.

Page 24: Building for Accessibility

Building for Accessibility

Page 25: Building for Accessibility

Page LoadingWe want to emulate the page load behavior

demonstrated with static pages.

Page 26: Building for Accessibility

End-User Goals• Have the screen reader automatically start reading

the content of the page.

• Have it start reading the content from the best point in the application hierarchy.

• Make it clear to the user that the content on the page has changed.

• Follow other recommended patterns that screen reader users are familiar with.

Page 27: Building for Accessibility

Ember Goals• Have the solution work with current idiomatic

Ember code or minimize migration cost.

• Make the change in a backwards compatible way to meet Ember's stability without stagnation goal.

• The default approach should be accessible, API design is a feature.

• Provide for extensibility with hooks enabling enhancement of this higher-level feature.

Page 28: Building for Accessibility

Exploration

Page 29: Building for Accessibility

InventoryRouter, Transitions, Routes,

Templates, Outlets, HTMLBars

Page 30: Building for Accessibility

Outlet FocusingWhat if we set the focus on the route's outlet immediately

after the transition completes?

Page 31: Building for Accessibility

Research

Page 32: Building for Accessibility

Screen Readers• It's like the Internet Explorer and Netscape HTML/

CSS/JS compatibility workarounds all over again.

• Screen readers tend to read whatever you focus.

• Nobody likes being dumped into forms mode.

• Screen readers are aware of content on the page changing, but don't present that to the user until it is asked for.

Page 33: Building for Accessibility

Ember• The top level outlet is generated and wrapped in a

containing DIV.

• All other outlets are populated by their templates without first being wrapped in a containing DIV.

• Routes have no reference to their rendered output.

• You can have multiple outlets in a single route.

• No-op transitions trigger no route hooks.

Page 34: Building for Accessibility

Solution Design

Page 35: Building for Accessibility

API DesignIt'd be nice if every route had a `focus` hook that was

called with the outlet contents.

Page 36: Building for Accessibility

Ember.Route.reopen({! focus(morph) {! var elem = morph.firstNode;!! try {! if (!elem.getAttribute('tabindex')) {! if (isInteractive(elem)) {! elem.setAttribute('tabindex', 0);! } else {! elem.setAttribute('tabindex', -1);! }! }!! elem.focus();! } catch (e) {}! }!});

Page 37: Building for Accessibility

DevelopmentHow do we call the `focus` hook?

Page 38: Building for Accessibility

Ember.Route.reopen({! enter(transition) {! var route = this;!! // Focus "up one level" for index routes.! if (! transition.pivotHandler &&! this.routeName === transition.pH.routeName + '.index'! ) {! transition.pivot = transition.pivotHandler.routeName;! route = transition.pivotHandler;! this._focus(route, transition);! }!! // Handle fresh entries.! if (!transition.pivot) {! transition.pivot = this.routeName;! this._focus(route, transition)! }!! return this._super(...arguments);! }!});

Page 39: Building for Accessibility

Ember.Route.reopen({! _focus(route, transition, parent) {! var focus = new Ember.RSVP.Promise(function(resolve, reject) {! this.focusPromiseResolve = resolve;! }.bind(route));!! // Set up our context for after the transition completes.! var transitionResolve = (function(transition, route) {! return function(result) {! delete transition.pivot;!! Ember.run.scheduleOnce('afterRender', route, function() {! route.focus(result.focus)! });! };! })(transition, route);!! // Clean up after ourselves in case there is a transition.retry() call.! var transitionReject = (function(transition, route) {! return function() {! delete transition.pivot;! };! })(transition, route);!! Ember.RSVP.hash({ focus, transition })! .then(transitionResolve)! .catch(transitionReject);! }!});

Page 40: Building for Accessibility

IntegrationWhat happens when Ember needs to be modified.

Page 41: Building for Accessibility

diff --git a/packages/ember-htmlbars/lib/keywords/outlet.js b/packages/ember-htmlbars/lib/keywords/outlet.js!index 317e899..6b01753 100644!--- a/packages/ember-htmlbars/lib/keywords/outlet.js!+++ b/packages/ember-htmlbars/lib/keywords/outlet.js!@@ -17,6 +17,10 @@ export default function(morph, env, scope, params, hash, template, inverse, visi!+ if (env.outletState.main.render.focusPromiseResolve) {!+ env.outletState.main.render.focusPromiseResolve(morph);!+ delete env.outletState.main.render.focusPromiseResolve;!+ }! keyword('@real_outlet', morph, env, scope, params, hash, template, inverse, visitor);!!diff --git a/packages/ember-routing/lib/system/router.js b/packages/ember-routing/lib/system/router.js!index bb157c1..5600f99 100644!--- a/packages/ember-routing/lib/system/router.js!+++ b/packages/ember-routing/lib/system/router.js!@@ -202,10 +202,18 @@ var EmberRouter = EmberObject.extend(Evented, {! for (var j = 0; j < connections.length; j++) {!+ delete connections[j].focusPromiseResolve;! var appended = appendLiveRoute(liveRoutes, defaultParentState, connections[j]);! liveRoutes = appended.liveRoutes;! if (appended.ownState.render.name === route.routeName || appended.ownState.render.outlet === 'main') {! ownState = appended.ownState;!+ // Pass forward the focus promise resolve hook from the route to the appropriate connection.!+ if (route.focusPromiseResolve) {!+ ownState.render.focusPromiseResolve = route.focusPromiseResolve;!+ delete route.focusPromiseResolve;!+ }

Page 42: Building for Accessibility

Contributing Back

Page 43: Building for Accessibility

Write an RFC!You've created and tested a feature!

It's time to get it shipped!

Page 44: Building for Accessibility

http://bit.ly/rfc66

Page 45: Building for Accessibility

Usage Notes• You can use this today! http://bit.ly/outletfocusing

• All template content must be wrapped in a `<div>`. Child outlets must also appear inside that `<div>`.

• Automatically generated templates are just `{{outlet}}` and will thus have problems.

• Provide feedback on RFC #66!

Page 46: Building for Accessibility

Demo

Page 47: Building for Accessibility

Learnings

• It's a different experience from the static site.

• We have programmatic control over the focusing behavior.

• Setting the focus has additional consequences in terms of scrolling behavior.

Page 48: Building for Accessibility

Challenge

Page 49: Building for Accessibility