Skip to content
This repository was archived by the owner on Apr 12, 2024. It is now read-only.

Commit c6909ed

Browse files
Marcy Suttoncaitp
Marcy Sutton
authored andcommitted
docs(guide/accessibility): Add in-depth guide
Closes #9930
1 parent 187e431 commit c6909ed

File tree

2 files changed

+139
-29
lines changed

2 files changed

+139
-29
lines changed

docs/content/guide/accessibility.ngdoc

Lines changed: 138 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -6,56 +6,165 @@
66

77
# Accessibility with ngAria
88

9-
You can use the `ngAria` module to have common ARIA attributes automatically applied when you
10-
use certain directives. To enable `ngAria`, just require the module into your application and
11-
the code will hook into your ng-show/ng-hide, input, textarea, button, select and
12-
ng-required directives and add the appropriate ARIA states and properties.
9+
The goal of ngAria is to improve Angular's default accessibility by enabling common
10+
[ARIA](http://www.w3.org/TR/wai-aria/) attributes that convey state or semantic information for
11+
assistive technologies used by persons with disabilities.
12+
13+
##Including ngAria
14+
15+
Using ngAria is as simple as requiring the ngAria module in your application. ngAria hooks into
16+
standard AngularJS directives and quietly injects accessibility support into your application
17+
at runtime.
18+
19+
```js
20+
angular.module('myApp', ['ngAria'])...
21+
```
22+
23+
Currently, ngAria interfaces with the following directives:
24+
25+
* <a href="#ngmodel">ngModel</a>
26+
* <a href="#ngdisabled">ngDisabled</a>
27+
* <a href="#ngshow">ngShow</a>
28+
* <a href="#nghide">ngHide</a>
29+
* <a href="#ngclick-and-ngdblclick">ngClick</a>
30+
* <a href="#ngclick-and-ngdblclick">ngDblClick</a>
31+
32+
<h2 id="ngmodel">ngModel</h2>
33+
34+
Most of ngAria's heavy lifting happens in the [ngModel](https://docs.angularjs.org/api/ng/directive/ngModel)
35+
directive. For elements using ngModel, special attention is paid by ngAria if that element also
36+
has a a role or type of `checkbox`, `radio`, `range` or `textbox`.
37+
38+
For those elements using ngModel, ngAria will dynamically bind and update the following ARIA
39+
attributes (if they have not been explicitly specified by the developer):
1340

14-
Currently, the following attributes are implemented:
15-
* aria-hidden
1641
* aria-checked
17-
* aria-disabled
18-
* aria-required
19-
* aria-invalid
20-
* aria-multiline
21-
* aria-valuenow
2242
* aria-valuemin
2343
* aria-valuemax
24-
* tabindex
25-
26-
You can disable individual attributes by using the `{@link ngAria.$ariaProvider#config config}` method.
44+
* aria-valuenow
45+
* aria-invalid
46+
* aria-required
2747

2848
###Example
2949

30-
```js
31-
angular.module('myApp', ['ngAria'])...
50+
```html
51+
<md-checkbox ng-model="val" required>
3252
```
3353

34-
Elements using `ng-model` with `required` or `ngRequired` directives will automatically have
35-
`aria-required` attributes with the proper corresponding values.
54+
Becomes:
3655

3756
```html
38-
<material-input ng-model="val" required>
57+
<md-checkbox ng-model="val" required aria-required="true" tabIndex="0">
58+
```
59+
60+
ngAria will also add `tabIndex`, ensuring custom elements with these roles will be reachable from
61+
the keyboard. It is still up to **you** as a developer to **ensure custom controls will be
62+
operable** from the keybard. Think of `ng-click` on a `<div>` or `<md-checkbox>`: you still need
63+
to bind `ng-keypress` to make it fully operable from the keyboard. As a rule, any time you create
64+
a widget involving user interaction, be sure to test it with your keyboard and at least one mobile
65+
and desktop screen reader (preferably more).
66+
67+
<h2 id="ngdisabled">ngDisabled</h2>
68+
69+
The `disabled` attribute is only valid for certain elements such as `button`, `input` and
70+
`textarea`. To properly disable custom element directives such as `<md-checkbox>` or `<taco-tab>`,
71+
using ngAria with [ngDisabled](https://docs.angularjs.org/api/ng/directive/ngDisabled) will also
72+
add `aria-disabled`. This tells assistive technologies when a non-native input is disabled, helping
73+
custom controls to be more accessible.
74+
75+
###Example
76+
77+
```html
78+
<md-checkbox ng-disabled="disabled">
3979
```
4080

4181
Becomes:
4282

4383
```html
44-
<material-input ng-model="val" required aria-required="true">
84+
<md-checkbox disabled aria-disabled="true">
4585
```
4686

47-
ngAria is just a starting point. You'll have to manually choose how to implement some
48-
accessibility features.
87+
>You can check whether a control is legitimately disabled for a screen reader by visiting
88+
[chrome://accessibility](chrome://accessibility).
4989

50-
For instance, you may want to add `ng-keypress` bindings alongside `ng-click` to make keyboard
51-
navigation easier.
90+
<h2 id="ngshow">ngShow</h2>
5291

92+
>The [ngShow](https://docs.angularjs.org/api/ng/directive/ngShow) directive shows or hides the
93+
given HTML element based on the expression provided to the `ngShow` attribute. The element is
94+
shown or hidden by removing or adding the `.ng-hide` CSS class onto the element.
5395

54-
## Additional Resources
96+
In its default setup, ngAria for `ngShow` is actually redundant. It toggles `aria-hidden` on the
97+
directive when it is hidden or shown. However, the default CSS of `display: none !important`,
98+
already hides child elements from a screen reader. It becomes more useful when the default
99+
CSS is overridden with properties that don’t affect assistive technologies, such as `opacity`
100+
or `transform`. By toggling `aria-hidden` dynamically with ngAria, we can ensure content visually
101+
hidden with this technique will not be read aloud in a screen reader.
102+
103+
One caveat with this combination of CSS and `aria-hidden`: you must also remove links and other
104+
interactive child elements from the tab order using `tabIndex=“-1”` on each control. This ensures
105+
screen reader users won't accidentally focus on "mystery elements". Managing tab index on every
106+
child control can be complex and affect performance, so it’s best to just stick with the default
107+
`display: none` CSS. See the [fourth rule of ARIA use](http://www.w3.org/TR/aria-in-html/#fourth-rule-of-aria-use).
108+
109+
<h2 id="nghide">ngHide</h2>
110+
111+
>The [ngHide](https://docs.angularjs.org/api/ng/directive/ngHide) directive shows or hides the
112+
given HTML element based on the expression provided to the `ngHide` attribute. The element is
113+
shown or hidden by removing or adding the `.ng-hide` CSS class onto the element.
114+
115+
The default CSS for `ngHide`, the inverse method to `ngShow`, makes ngAria redundant. It toggles
116+
`aria-hidden` on the directive when it is hidden or shown, but the content is already hidden with
117+
`display: none`. See explanation for <a href="#ngshow">ngShow</a> when overriding the default CSS.
118+
119+
<h2 id="ngclick">ngClick and ngDblClick</h2>
120+
If `ngClick` or `ngDblClick` is encountered, ngAria will add `tabIndex` if it isn't there already.
121+
Even with this, you must currently still add `ng-keypress` to non-interactive elements such as
122+
`<div>` or `<taco-button>` to enable keyboard access. I have recommended this also bind
123+
`ng-keypress` to be more useful; the conversation is [currently ongoing](https://github.com/angular/angular.js/issues/9254).
124+
125+
* * *
126+
127+
##Disabling attributes
128+
The attribute magic of ngAria may not work for every scenario. To disable individual attributes,
129+
you can use the `{@link ngAria.$ariaProvider#config config}` method:
130+
131+
```
132+
angular.module('myApp', ['ngAria'], function config($ariaProvider) {
133+
$ariaProvider.config({
134+
tabindex: false
135+
});
136+
});
137+
```
138+
* * *
139+
140+
##Common Accessibility Patterns
55141

56142
Accessibility best practices that apply to web apps in general also apply to Angular.
57143

58-
* [A11Y Project](http://a11yproject.com/)
59-
* [WebAim](http://webaim.org/)
60-
* [Using WAI-ARIA in HTML](http://www.w3.org/TR/2014/WD-aria-in-html-20140626/)
61-
* [Apps For All: Coding Accessible Web Applications](https://shop.smashingmagazine.com/apps-for-all-coding-accessible-web-applications.html)
144+
* **Text alternatives**: Add alternate text content to make visual information accessible using
145+
[these W3C guidelines](http://www.w3.org/TR/html-alt-techniques/). The appropriate technique
146+
depends on the specific markup but can be accomplished using offscreen spans, `aria-label` or
147+
label elements, image `alt` attributes, `figure`/`figcaption` elements and more.
148+
* **HTML Semantics**: If you're creating custom element directives, Web Components or HTML in
149+
general, use native elements wherever possible to utilize built-in events and properties.
150+
Alternatively, use ARIA to communicate semantic meaning. See [notes on ARIA use](http://www.w3.org/TR/aria-in-html/#notes-on-aria-use-in-html).
151+
* **Focus management**: Guide the user around the app as views are appended/removed.
152+
Focus should *never* be lost, as this causes unexpected behavior and much confusion (referred to
153+
as "freak-out mode").
154+
* **Announcing changes**: When filtering or other UI messaging happens away from the user's focus,
155+
notify with [ARIA Live Regions](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/ARIA_Live_Regions).
156+
* **Color contrast and scale**: Make sure content is legible and interactive controls are usable
157+
at all screen sizes. Consider configurable UI themes for people with color blindness, low vision
158+
or other visual impairments.
159+
* **Progressive enhancement**: Some users do not browse with JavaScript enabled or do not have
160+
the latest browser. An accessible message about site requirements can inform users and improve
161+
the experience.
162+
163+
## Additional Resources
164+
165+
* [Using ARIA in HTML](http://www.w3.org/TR/aria-in-html/)
166+
* [AngularJS Accessibility at ngEurope](https://www.youtube.com/watch?v=dmYDggEgU-s&list=UUEGUP3TJJfMsEM_1y8iviSQ)
167+
* [Chrome Accessibility Developer Tools](https://chrome.google.com/webstore/detail/accessibility-developer-t/fpkknkljclfencbdbgkenhalefipecmb?hl=en)
168+
* [W3C Accessibility Testing](http://www.w3.org/wiki/Accessibility_testing)
169+
* [WebAIM](http://webaim.org)
170+
* [A11y Project](http://a11yproject.com)

docs/content/guide/index.ngdoc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ In Angular applications, you move the job of filling page templates with data fr
4444
* **Security:** {@link ng.$sce Strict Contextual Escaping}, {@link ng.directive:ngCsp Content Security Policy}, {@link ngSanitize.$sanitize $sanitize}, [video](https://www.youtube.com/watch?v=18ifoT-Id54)
4545
* **Internationalization and Localization:** {@link guide/i18n Angular Guide to i18n and l10n}, {@link ng.filter:date date filter}, {@link ng.filter:currency currency filter}, [Creating multilingual support](http://www.novanet.no/blog/hallstein-brotan/dates/2013/10/creating-multilingual-support-using-angularjs/)
4646
* **Mobile:** {@link ngTouch Touch events}
47+
* **Accessibility:** {@link guide/accessibility ngAria}
4748

4849
### Testing
4950

0 commit comments

Comments
 (0)