Skip to content

Commit 8932611

Browse files
alex-barstowgkatsev
authored andcommitted
fix(a11y): current time and duration display accessibility with VoiceOver (videojs#5653)
The desired behavior when navigating any of the TimeDisplay components (current time, duration, remaining time) with the arrow keys with a screen reader is for the singular parent div to receive focus, and the reader should announce the text of each child span in order, ex. "Current Time 0:17" and "Duration 1:10". This is how it works when using JAWS. However, with VoiceOver each individual child span element receives focus and the contents are announced separately. According to the ARIA spec (see [here](https://www.w3.org/TR/html-aam-1.0/#details-id-124) and [example 8](https://www.w3.org/TR/wai-aria-1.1/#presentation)), there is no implicit role for span elements, so the contents should be exposed but the elements themselves should be invisible to screen readers. In other words, <span> Sample Content </span> should be the same as <span role="presentation"> Sample Content </span>. But this is not the case with VoiceOver. As far as I can tell, the desired behavior is only achieved with VoiceOver if each child span is explicitly made presentational, either by assigning each of them the presentation role, or by assigning the parent div a role that makes its children presentational (although there doesn't seem to be a role whose semantics fit the purpose of that div) The first ARIA doc link above shows the Mac OS X Accessibility Protocol mapping for span elements is to the group role. I don't know enough about accessibility API mapping to confidently draw conclusions about root cause, but this seems like a possible explanation. Changes: * add role="presentation" to each of the two span elements inside TimeDisplay divs * add aria-hidden="true to the TimeDivider (tangential improvement) * fix inaccurate description of the TimeDisplay component (tangential improvement)
1 parent b9d8744 commit 8932611

File tree

2 files changed

+13
-3
lines changed

2 files changed

+13
-3
lines changed

src/js/control-bar/time-controls/time-display.js

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import {bind, throttle} from '../../utils/fn.js';
88
import formatTime from '../../utils/format-time.js';
99

1010
/**
11-
* Displays the time left in the video
11+
* Displays time information about the video
1212
*
1313
* @extends Component
1414
*/
@@ -39,14 +39,19 @@ class TimeDisplay extends Component {
3939
const className = this.buildCSSClass();
4040
const el = super.createEl('div', {
4141
className: `${className} vjs-time-control vjs-control`,
42-
innerHTML: `<span class="vjs-control-text">${this.localize(this.labelText_)}\u00a0</span>`
42+
innerHTML: `<span class="vjs-control-text" role="presentation">${this.localize(this.labelText_)}\u00a0</span>`
4343
});
4444

4545
this.contentEl_ = Dom.createEl('span', {
4646
className: `${className}-display`
4747
}, {
4848
// tell screen readers not to automatically read the time as it changes
49-
'aria-live': 'off'
49+
'aria-live': 'off',
50+
// span elements have no implicit role, but some screen readers (notably VoiceOver)
51+
// treat them as a break between items in the DOM when using arrow keys
52+
// (or left-to-right swipes on iOS) to read contents of a page. Using
53+
// role='presentation' causes VoiceOver to NOT treat this span as a break.
54+
'role': 'presentation'
5055
});
5156

5257
this.updateTextNode_();

src/js/control-bar/time-controls/time-divider.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,11 @@ class TimeDivider extends Component {
2121
return super.createEl('div', {
2222
className: 'vjs-time-control vjs-time-divider',
2323
innerHTML: '<div><span>/</span></div>'
24+
}, {
25+
// this element and its contents can be hidden from assistive techs since
26+
// it is made extraneous by the announcement of the control text
27+
// for the current time and duration displays
28+
'aria-hidden': true
2429
});
2530
}
2631

0 commit comments

Comments
 (0)