CQS: answer drilldown accessibility

This patch provides two a11y enhancements:

  - question statistics now have an invisible h4 that reads the question
    position, so the listening user can tell which question we're
    actually talking about
  - when you click the "Toggle Details" button, the new state of the
    button is read automatically by the SR

Closes CNVS-15305

TEST PLAN
---- ----

  - for a quiz with at least 1 question, go to statistics CQS page
  - search for headings using the screen reader and verify that each
    question box has a heading that reads "Question X" where X is the
    position of the question
  - tab through to the "Toggle Details" button for a question and press
    it
    + verify you hear "Hide answer details"
    + press it again
      - verify you hear "Show answer details" again

Change-Id: I85ddcc6219c0022e7979d06ba224de856575076f
Reviewed-on: https://gerrit.instructure.com/40777
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 09:49:56 +03:00
parent 2591aba7ee
commit 93631a703c
7 changed files with 30 additions and 8 deletions

View File

@ -2,9 +2,17 @@
define(function(require) {
var React = require('react');
var ScreenReaderContent = React.createClass({
getDefaultProps: function() {
return {
tagName: 'span'
};
},
render: function() {
return(
<span className="screenreader-only">{this.props.children}</span>
var tag = React.DOM[this.props.tagName];
return this.transferPropsTo(
<tag className="screenreader-only" children={this.props.children} />
);
}
});

View File

@ -26,6 +26,7 @@ define(function() {
'question_text',
'responses',
'answers',
'position',
// multiple-choice & true/false
'answered_student_count',
@ -83,4 +84,4 @@ define(function() {
PROGRESS_COMPLETE: 'completed',
PROGRESS_FAILED: 'failed',
};
});
});

View File

@ -53,7 +53,8 @@ define(function(require) {
participantCount={this.props.participantCount}
onToggleDetails={this.props.onToggleDetails}
expanded={this.props.expanded}
questionText={this.props.questionText} />
questionText={this.props.questionText}
position={this.props.position} />
<nav className="row-fluid answer-set-tabs">
{this.props.answerSets.map(this.renderAnswerSetTab)}

View File

@ -3,10 +3,12 @@ define(function(require) {
var React = require('react');
var I18n = require('i18n!quiz_statistics');
var ToggleDetailsButton = require('jsx!./toggle_details_button');
var ScreenReaderContent = require('jsx!../../components/screen_reader_content');
var QuestionHeader = React.createClass({
getDefaultProps: function() {
return {
position: 1,
responseCount: 0,
participantCount: 0,
onToggleDetails: null,
@ -18,6 +20,10 @@ define(function(require) {
render: function() {
return (
<header>
<ScreenReaderContent tagName="h4">
{I18n.t('question_header', 'Question %{position}', { position: this.props.position })}
</ScreenReaderContent>
<span className="question-attempts">
{I18n.t('attempts', 'Attempts: %{count} out of %{total}', {
count: this.props.responseCount,
@ -44,4 +50,4 @@ define(function(require) {
});
return QuestionHeader;
});
});

View File

@ -22,7 +22,8 @@ define(function(require) {
participantCount={this.props.participantCount}
onToggleDetails={this.props.onToggleDetails}
expanded={this.props.expanded}
questionText={this.props.questionText} />
questionText={this.props.questionText}
position={this.props.position} />
<div key="charts">
<CorrectAnswerDonut correctResponseRatio={rr} />

View File

@ -23,7 +23,8 @@ define(function(require) {
participantCount={props.participantCount}
onToggleDetails={props.onToggleDetails}
expanded={props.expanded}
questionText={props.questionText} />
questionText={props.questionText}
position={this.props.position} />
<div key="charts">
<CorrectAnswerDonut correctResponseRatio={crr} />

View File

@ -37,7 +37,11 @@ define(function(require) {
}
return(
<button title={label} onClick={this.props.onClick} className="btn">
<button
title={label}
onClick={this.props.onClick}
className="btn"
aria-live="polite">
<ScreenReaderContent children={label} />
{isExpanded ?