On Github marcysutton / accessibility-of-mvcs
Everyone can perceive, understand, navigate, and interact with the Web, and they can contribute to the Web.
Millions of people have disabilities that affect their use of the Web.
Web accessibility also benefits people without disabilities.
Refer to slide #2 about the kinds of apps we build.
Expands HTML's semantic vocabulary
What does this thing do?
<div role="img" style="background-image..."></div>
The current condition of this particular thing
<material-input aria-disabled="true"></material-input>
The nature of the current object
<doner-kebab aria-label="Lunch courtesy AngelinaMagnum">
Disables a screen reader’s “virtual cursor”
<sparkle-party role="application"></sparkle-party>
Marco Zehe's post about using Application Mode
Virtual Cursor/Browse mode: Several keys are captured by the assistive technology and are not processed by the browser. These allow navigation by headings, lists, links, tables, form elements and others. Usually, these are done via single letters. The visual focus may or may not follow the virtual cursor onto focusable items, depending on the assistive technology in use and its settings
Forms mode/focus mode: All keys are passed through to the browser. The challenge is that you may be creating widgets that require you to force the user into direct interaction with the browser. You know that your widget can best be used via the keyboard if the user is not in virtual mode. It is under your control whether the user is being thrown into focus mode once your widget gains keyboard focus.
<body role="application">
<sparkle-party> <h2>Do you like to dance?</h2> <button class="lets-dance">I wore my party pants</button> <disco-ball> <canvas></canvas> <p aria-live="polite" class="disco-transcript"></p> </disco-ball> </sparkle-party>Client-side apps often blur the lines between application and document. Because accessibility works best with a document structure, it's best to selectively use the application role on a per-widget basis. Care must also be taken for the correct roles, states and properties for non-native elements or interactions.
<div tabIndex="0"></div>
<dance-button tabIndex="0" ng-click="spicy123(go);"> DANCE! </dance-button>
<dance-button tabIndex="0" role="button" ng-click="letsGetDown(toThat)" ng-keypress="letsGetDown(toThat)"> DANCE! </dance-button>DANCE!
[tabIndex="0"] { color: $linkColor; &:focus, &:hover { color: $linkActiveColor; outline: default; } }
Photo by Matthew Bergman
{{party-pants}}
App.PartyPantsComponent = Ember.Component.extend({ tagName: 'party-pants', ariaRole: 'article', attributeBindings: ['tabIndex'], tabIndex: function() { return this.get('active') ? 0 : -1; }.property('active') });
// AngularUI Bootstrap <accordion-group is-open="status.open" is-disabled="status.isDisabled"> </accordion-group>
// AngularUI Bootstrap <accordion-group aria-expanded="true" is-open="status.open" aria-disabled="false" is-disabled="status.isDisabled"> </accordion-group>Angular properties alongside aria properties get verbose.
// AngularUI Bootstrap <accordion-group ng-expanded="status.open" ng-disabled="status.isDisabled"> </accordion-group>
<material-radio-group ng-model="data.group"> <material-radio-button value="1"> Label 1 </material-radio-button> <material-radio-button value="2"> Label 2 </material-radio-button> </material-radio-group>
function materialRadioGroupDirective() { element.attr({ 'role': 'radiogroup', 'tabIndex': '0' }) .on('keydown', keydownListener); function keydownListener(ev) { if (ev.which === Constant.KEY_CODE.LEFT_ARROW) { rgCtrl.selectPrevious(element); } else if (ev.which === Constant.KEY_CODE.RIGHT_ARROW) { rgCtrl.selectNext(element); } } } function materialRadioButtonDirective($expectAria) { element.attr('role', 'radio'); $expectAria(element, 'aria-label', element.text()); var lastChecked; attr.observe('value', render); function render() { var checked = (rgCtrl.getViewValue() === attr.value); if(checked === lastChecked){ return; } lastChecked = checked; element.attr('aria-checked', checked); } }