Developments in Angular Accessibility



Developments in Angular Accessibility

3 10


angular-a11y

Slides for Angular.js Accessibility at CSUN 2015 (previously at ngEurope)

On Github marcysutton / angular-a11y

Accessible Angular.js

Accessibility is about people.

Accessible Angular.js

Marcy Sutton, Seattle, USAAccessibility Engineer, Angular Core Team Member

http://marcysutton.com/gotocon

#AngularJS web apps are never accessible because even the books on it start with inaccessible code samples! Paul J Adam January 2, 2015

& Me

Today

  • Material Design & a11y
  • ngAria
  • Protractor
  • Angular 2

Legend: waffle denotes a major topic in client-rendered app accessibility

Material Design

Material Design for Angular 1.x

Interactivity

Toolbar

Checkbox
Switch
Button Button Button
Dogs
Cats
Pigs

Reachable Controls

      <md-checkbox tabindex="0" ...

              
Add tabindex

Operable Controls

      <md-checkbox tabindex="0" 
                   ng-keypress="doStuff()" ...
              
Enable keyboard events

Semantics

    Button
        // should be:
    Button
          

ARIA

      <md-checkbox tabindex="0" role="checkbox" aria-checked="true">
        Checkbox
      </md-checkbox>
          
Roles, states and properties

Text Alternatives

   Menu
          
   Waffles!
   
   
          
   

Enforcing text alternatives

Angular Material Radio Buttons opens in a new window Also: form labels, icon buttons, background images with embedded text, etc.

Fixing ARIA warnings

  <md-radio-group ng-model="data.group3">
    <md-radio-button ng-repeat="it in avatarData"
                     ng-value="it.value">
        <md-icon md-svg-icon="{{it.id}}"></md-icon>
    </md-radio-button>
  </md-radio-group>

              

aria-label is missing.

  <md-radio-group ng-model="data.group3">
    <md-radio-button ng-repeat="it in avatarData"
                     ng-value="it.value"
                     aria-label="{{it.title}}">
        <md-icon md-svg-icon="{{it.id}}"></md-icon>
    </md-radio-button>
  </md-radio-group>

              

Boom! Labeled radio buttons.

Focus management

Focus management

  <md-sidenav class="md-sidenav-right" md-component-id="right">
    <md-content ng-controller="RightCtrl">
      <form>
        <md-input-container>
          <label for="testInput">Test input</label>
          <input type="text" id="testInput"
                 ng-model="data" md-sidenav-focus>
        </md-input-container>
      </form>
      <md-button ng-click="close()" class="md-primary">
        Close
      </md-button>
    </md-content>
  </md-sidenav>
          
Angular Material Sidenav with custom focus

Notifying the User

Angular Material Autocomplete with 4 Matches

Notifying the User (code)

  <aria-status role="status" aria-live="assertive">
    <p ng-repeat="message in messages">{{message}}</p>
  </aria-status>
          
  switch (self.matches.length) {
    case 0:  return 'There are no matches available.';
    case 1:  return 'There is 1 match available.';
    default: return 'There are ' + self.matches.length + ' matches available.';
  }
          
Angular Material Autocomplete Source

Angular ❤ Open Source

ngAria

Accessibility Module in Angular 1.3+

https://docs.angularjs.org/guide/accessibility

Including ngAria

  angular.module('app', ['ngAria'], function($ariaProvider) {
    $ariaProvider.config({
      ariaHidden: false
    ...
          
    <body>
      <!-- page content here -->
      <script src="angular.min.js"></script>
      <script src="angular-aria.js"></script>
    </body>
          

ngAria

Adds support to these directives:

  • ngModel
  • ngDisabled
  • ngShow
  • ngHide
  • ngClick
  • ngDblClick
  • ngMessages

ngAria & ngDisabled

  <md-checkbox ng-disabled="true" aria-disabled="true"...
            
  .directive('ngDisabled', ['$aria', function($aria) {
    return $aria.$$watchExpr('ngDisabled', 'aria-disabled');
  }])
            
ngAria Source for ngDisabled for ngDisabled opens in a new window

ngClick

      <div ng-click="ohNoYouDidnt()"></div>
            

ngAria & ngClick

 .directive('ngClick',['$aria', function($aria) {
    return {
      compile: function(scope, elem, attr) {
        var nodeBlackList = ['BUTTON','A','INPUT','TEXTAREA','SELECT'];
        if (!isNodeOneOf(elem, nodeBlackList)) {
          if (!elem.attr('role') && config.buttonRole) {
            elem.attr('role', 'button');
          }
          if (config.bindKeypress) {
            elem.on('keypress', function(event) {
              if (event.keyCode === 32 || event.keyCode === 13) {
                scope.$apply(callback);
              ...
					
https://github.com/angular/angular.js/pull/10318 Opens in a new window

That's a lot of effort...

Just use buttons!

  • Node.js command line application
  • Runs on WebDriver
  • Choose your test framework
  • Great for continuous integration

Protractor A11Y Plugin

Test your site with:

https://github.com/angular/protractor Link opens in a new window

Protractor A11Y Plugin: Setup

  exports.config = {
    plugins: [{
      tenonIO: {
        options: {
          // options.src will be added by the test
        },
        printAll: false,
      },
      chromeA11YDevTools: true,
      path: 'node_modules/protractor/plugins/accessiblity'
    }]
  }
          
Plugin Documentation Link opens in a new window

Protractor Accessibility

Can I use?

Library Pricing API Key External Request No. of Tests Chrome Accessibility Developer Tools Free No No 14 Tenon.io Free limited accounts, paid subscriptions Yes Yes 63

Automated Testing Strategies

  • Check for Labels
  • Validate Roles
  • Watched ARIA Properties
  • Interactions
  • Color Contrast

Angular 2

http://angular.io

Changes in Angular 2

Event bindings

      <button ng-focus="anticipationEvent()"
              ng-click="deliverWaffles()" id="{{item.id}}">
        Give me waffles </button>
          
Angular 1: attributes
      <button (focus)="anticipationEvent()"
              (click)="deliverWaffles()" [waffle-id]="item.id">
        Give me waffles </button>
          
Angular 2: properties

Angular 2 includes ARIA support

Angular 2 on Github

Contribute!

https://github.com/angular/angular Link opens in a new window

Resources

All links open in new windows

The End.

Accessible Angular.js@marcysutton / marcysutton.com/gotocon

Accessible Angular.js Accessibility is about people.