Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Incrementing a `role="spinbutton"` with Voiceover

I'm struggling to implement an accessible input with increment/decrement behaviors, using an <input type="text" role="spinbutton" /> element in HTML/JavaScript. But it seems like with VoiceOver there are custom (fake?) input events for incrementing/decrementing which change the input's value in unexpected ways.

How do I make sure a user navigating the page with assistive technology doesn't get bad guidance from VoiceOver while trying to interact with my widget?

For example, using super trimmed-down code like this:

function logIt(...args) {
  document.getElementById('output').appendChild(
    document.createTextNode(`${args.join(', ')}\n`)
  );
}

document.getElementById("myInput").addEventListener('input', (e) => {
  debugger;
  logIt(e.type, e.data, String(e));
  e.target.setAttribute('aria-valuenow', e.target.value);
}, false);

document.getElementById("myInput").addEventListener('keydown', (e) => {
  logIt(e.type, e.data, String(e));
}, false);
      <input
        id="myInput"
        type="text"
        role="spinbutton"
        autocomplete="off"
        defaultValue="1"
        aria-valuenow="1"
        aria-valuemin="0"
        aria-valuemax="100"
      />
    </div>
    <pre id="output"></pre>

... VoiceOver will describe the input as a "stepper" and give instructions on how to increment/decrement using the keyboard. But using those keyboard commands results in some weird math, as seen in this screen cap:

animated screen capture of attempts to increment with VoiceOver keyboard

You can also see (from the "logging" in the screen cap) that when the user types input, an InputEvent is triggered with event.type being input - but when the VoiceOver keyboard command for increment/decrement is used, a base-type Event is triggered with event.type again set to input.

And this doesn't seem to be unique to my implementations of role="spinbutton". The jQuery UI spinner doesn't behave well when incremented/decremented using VoiceOver keyboard commands:

animated screen capture of jQuery UI spinner being incremented using VoiceOver and the value changing to some unexpected scientific notation

I even tried some of the w3c's examples for role="spinbutton":

  • The font size widget on https://www.w3.org/TR/wai-aria-practices/examples/toolbar/toolbar.html
  • The date picker on https://www.w3.org/TR/wai-aria-practices/examples/spinbutton/datepicker-spinbuttons.html

... and even though VoiceOver described each of those UI controls as a "stepper" and gave instructions on how to increment/decrement them using the keyboard, those instructions didn't seem to work. Other keyboard behaviors worked - but the ones VoiceOver suggests don't.

What can I do to make sure that role="spinbutton" markup works correctly with VoiceOver's increment/decrement keyboard commands?

like image 894
Richard JP Le Guen Avatar asked Dec 04 '19 13:12

Richard JP Le Guen


1 Answers

I don't believe role="spinbutton" is compatible with VoiceOver as it seems that VoiceOver hijacks the keydown events when using the VoiceOver cursor. So when focusing on an element with role="spinbutton" VoiceOver instructs the user to use "Control-Option DownArrow" or "Control-Option UpArrow" to decrement or increment the value. When those keys are pressed the event does not make it to any JavaScript keyDown event handler so we can't detect that those keys have been pressed and can't implement the actual incrementing or decrementing of the value. So I'm not sure there is any way to use role="spinbutton" and make it work with VoiceOver. The user will be given instructions that don't work and will be confusing.

As a workaround for an application that I'm working on I've implemented the key handling behavior described in the WAI ARIA authoring practices for spinbutton but I have not added role="spinbutton" or the other aria attributes listed. Instead, I've added aria-live="assertive" so that when the value is changed either by keyboard or clicking the increment/decrement buttons the user hears the new value. Additionally, I've added some visually hidden text that instructs the user on how to increment/decrement the value with the keyboard and associated that with the input using aria-describedby.

like image 69
SunshinyDoyle Avatar answered Oct 08 '22 21:10

SunshinyDoyle