CQS: DI help dialog toggle button a11y

This patch makes the button that opens the discrimination index help
dialog more accessible.

Closes CNVS-15306

Enhancements:

  - the "?" little icon now acts (and reads) like a button
  - button is now reachable via TAB
  - button now reads a descriptive message when the user focuses it:
    "Learn more about the Discrimination Index"
  - pressing RETURN while focusing the button will open the dialog
  - the SR starts reading the content of the dialog as soon as it
    is opened, instead of focusing the Close button or the link inside
  - the link used to read "here", now it contains the full message:
    "More information is available here." which is better

TEST PLAN
---- ----

  - go to statistics cqs with at least 1 multiple choice question
  - keep pressing TAB and verify you can focus the "?" icon
  - verify that you hear "Learn more ..." when you focus it
  - press RETURN
    + verify the dialog opens
    + the thing should start reading the little article in there
    + verify you can TAB to the "More info..." link in the article
      - click it and verify it takes you to the instructure help article
      - close the tab
    + press ESCAPE and verify the dialog closes, and your focus is back
      to the toggle button

Change-Id: I1b840ed82b9d71262c92372aeb7182ef76707fc9
Reviewed-on: https://gerrit.instructure.com/40779
Tested-by: Jenkins <jenkins@instructure.com>
QA-Review: Trevor deHaan <tdehaan@instructure.com>
Reviewed-by: Josh Simpson <jsimpson@instructure.com>
Product-Review: Ahmad Amireh <ahmad@instructure.com>
This commit is contained in:
Ahmad Amireh 2014-09-09 10:23:41 +03:00
parent 3f21967641
commit 7fd9d0fcf2
5 changed files with 68 additions and 8 deletions

View File

@ -4,6 +4,7 @@ define(function(require) {
var jQueryUIDialog = require('canvas_packages/jqueryui/dialog');
var $ = require('canvas_packages/jquery');
var _ = require('lodash');
var K = require('../constants');
var omit = _.omit;
/**
@ -112,7 +113,45 @@ define(function(require) {
* @property {Number} [width=300]
* How wide the dialog should start out, in pixels.
*/
width: React.PropTypes.number
width: React.PropTypes.number,
/**
* @property {Boolean} [autoOpen=false]
* Dialog option. When true, the dialog will open as soon as this
* component is mounted.
*/
autoOpen: React.PropTypes.bool,
/**
* @property {Boolean} [keyboardAccessible=true]
*
* If this is on, the toggle button will be tabbable (reached using TAB)
* and will intercept RETURN keypresses to show the dialog.
*
* Recommended!
*/
keyboardAccessible: React.PropTypes.bool,
/**
* @property {String} [role="button"]
* The ARIA role of the dialog toggle.
*/
role: React.PropTypes.string,
/**
* @property {String} aria-label
*
* A string to provide to screen-readers to tell the user that pressing
* this element will launch a specific dialog.
*
* A good example of a message:
*
* "Learn more about the Discrimination Index."
*
* That, coupled with a role of "button" will help the user understand
* what the toggle element really is.
*/
"aria-label": React.PropTypes.string,
},
getInitialState: function() {
@ -128,8 +167,10 @@ define(function(require) {
children: [],
autoOpen: false,
tagName: 'div',
role: 'button',
title: null,
width: 300
width: 300,
keyboardAccessible: true
};
},
@ -157,8 +198,12 @@ define(function(require) {
return (
<tag
onClick={this.toggle}
onKeyPress={this.openOnReturn}
className={this.props.className}
children={this.props.children} />
children={this.props.children}
role={this.props.role}
aria-label={this.props['aria-label']}
tabIndex={this.props.keyboardAccessible ? "0" : undefined} />
);
},
@ -167,6 +212,13 @@ define(function(require) {
this.__send('open');
},
openOnReturn: function(e) {
if (this.props.keyboardAccessible && e.which === K.KC_RETURN) {
e.preventDefault();
this.open();
}
},
/** Close the dialog */
close: function() {
this.__send('close');
@ -231,7 +283,11 @@ define(function(require) {
},
__getContentProps: function(props) {
return omit(props, [ 'className', 'tagName', 'content', 'children' ]);
return omit(props, [
'className', 'tagName', 'content', 'children',
'width', 'title', 'autoOpen',
'aria-label', 'role', 'keyboardAccessible'
]);
}
});

View File

@ -59,7 +59,7 @@ define(function(require) {
//>>excludeEnd("production");
render: function() {
return <div dangerouslySetInnerHTML={{__html: this.state.markup }} />;
return <div aria-role="article" dangerouslySetInnerHTML={{__html: this.state.markup }} />;
}
});

View File

@ -83,5 +83,7 @@ define(function() {
PROGRESS_ACTIVE: 'running',
PROGRESS_COMPLETE: 'completed',
PROGRESS_FAILED: 'failed',
KC_RETURN: 13
};
});

View File

@ -151,7 +151,9 @@ define(function(require) {
title={I18n.t('discrimination_index_dialog_title', 'The Discrimination Index Chart')}
content={Help}
width={550}
className="chart-help-trigger icon-question" />
className="chart-help-trigger icon-question"
aria-label={I18n.t('discrimination_index_dialog_trigger', 'Learn more about the Discrimination Index.')}
tabIndex="0" />
</p>
{Chart(chartData)}

View File

@ -11,7 +11,7 @@ define(function(require) {
<Text
phrase="discrimination_index_help"
articleUrl={K.DISCRIMINATION_INDEX_HELP_ARTICLE_URL}>
<p>
<p tabIndex="0" autoFocus>
This metric provides a measure of how well a single question can tell the
difference (or discriminate) between students who do well on an exam and
those who do not.
@ -23,7 +23,7 @@ define(function(require) {
</p>
<p>
More information is available <a href="%{article_url}" target="_blank">here</a>.
<a href="%{article_url}" target="_blank">More information is available here.</a>
</p>
</Text>
);