Page MenuHomePhabricator

Reconsider `disabled` and `tabindex=-1` on disabled elements
Open, MediumPublic

Description

While updating :focus states on Apex widgets, disabled PHP DropdownInputWidget grabbed my focus:
We're currently, as of v0.22.3, delivering following output:

<div aria-disabled="true" id="ooui-168" class="oo-ui-widget oo-ui-widget-disabled oo-ui-inputWidget oo-ui-dropdownInputWidget oo-ui-dropdownInputWidget-php" data-ooui="{&quot;_&quot;:&quot;OO.ui.DropdownInputWidget&quot;,&quot;options&quot;:[],&quot;inputId&quot;:&quot;ooui-34&quot;,&quot;disabled&quot;:true}">
    <select tabindex="-1" aria-disabled="true" disabled="disabled" id="ooui-34" class="oo-ui-inputWidget-input oo-ui-indicator-down"></select>
</div>

The select element carries tabindex="-1" aria-disabled="true" disabled="disabled"

There are various issues with this combination:

disabled=true attribute implies that an element isn't focusable at all and browsers won't fire attached events.
Depending on the context, it can be important to have focusable disabled elements with only aria-disabled=true applied, which will be only read “dimmed” to screenreader users.
Thinking of forms with process steps where it's useful to give feedback what's disabled instead of just jumping to the next enabled widget.

Event Timeline

Volker_E triaged this task as Medium priority.Jul 31 2017, 1:48 PM
Volker_E added a project: OOUI.
Volker_E updated the task description. (Show Details)

Note that non-focusable != ignored by screenreaders (that's aria-hidden). Just because something is not in the focus sequence of keyboard controls does not generally mean much to the cursor of screenreaders. They are two separate 'cursors' (one on the visual dom, and the other on the accessibility dom).

keyboard accessibility != screenreader accessibility

@TheDJ Yes, I seemingly wasn't clear enough in the description. :)
When setting disabled attribute there have been screenreaders/browser combinations, where the element is completely left out by the screenreader.

I consider those screenreader/browser combinations broken in that case and we should file tickets with them to report this broken behavior. aria-disabled and the html5 disabled attribute are intended to be functionally equivalent from the perspective of a screenreader and neither of them should ever be completely ignored by the screenreader. The ARIA spec notes they are "perceivable but disabled, so it is not editable or otherwise operable"

The whole point of aria attributes is to force a behaviour on an arbitrary html fragment. The only reason we set aria-disabled on elements with disabled, is in order to support browsers that don't support HTML5 attributes yet.

In my opinion we should use the best, most compliant form of aria attributes and semantic DOM as possible, because that will likely be the most future proof one. Only if that proves to create significant interaction problems, we might consider diverting from that, but if we write around the screenreader/browser bugs then we simply postpone them getting fixed.

This is a result of how "generic" our code is:

  • tabindex="-1" aria-disabled="true" comes from TabIndexedElement::updateTabIndex() (which doesn't "know" we're dealing with a <select> rather than a generic <div> or something)
  • disabled="disabled" comes from InputWidget::setDisabled()

Note that this affects all InputWidget subclasses, not just DropdownInputWidget.

If this is causing any practical issues, we could add an override method InputWidget::updateTabIndex() to clear the unwanted attributes (and restore "real" tabindex I guess). A similar change would be needed in JS code for consistency.

(We've done a similar thing elsewhere – ButtonInputWidget::setLabel() overrides LabelElement::setLabel(), you can use that as an example.)

I consider those screenreader/browser combinations broken in that case and we should file tickets with them to report this broken behavior. aria-disabled and the html5 disabled attribute are intended to be functionally equivalent from the perspective of a screenreader and neither of them should ever be completely ignored by the screenreader. The ARIA spec notes they are "perceivable but disabled, so it is not editable or otherwise operable"

Found an comment about VoiceOver behaviour from May 2017, restating here that “aria-disabled="true" will still be able to receive focus and report to the screen reader as dimmed” while disabled will be completely ignored. Haven't tested in most recent VO.