Skip to content

Commit

Permalink
fix(aria-hidden-focusable): disabled aria-hidden fieldset should not …
Browse files Browse the repository at this point in the history
…have focusable children (#3056)

* fieldset that's hidden and disabled should mean input inside is not focusable

* only return true if elements are in same shadow tree

* use break

* fix performance issue

* change target to fieldset element

* do caching better

* fix return value

* more caching
  • Loading branch information
clottman committed Jul 15, 2021
1 parent f5cc0a6 commit 0865bd7
Show file tree
Hide file tree
Showing 2 changed files with 83 additions and 1 deletion.
39 changes: 38 additions & 1 deletion lib/commons/dom/focus-disabled.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,50 @@ function focusDisabled(el) {
return true;
}

// if a form element is in a legend, that element will not be disabled even if the fieldset is
// https://developer.mozilla.org/en-US/docs/Web/HTML/Element/fieldset
let parentNode = vNode.parent;
const ancestors = [];
let fieldsetDisabled = false;
while (
parentNode &&
parentNode.shadowId === vNode.shadowId &&
!fieldsetDisabled
) {
ancestors.push(parentNode);
if (parentNode.props.nodeName === 'legend') {
break;
}

// use the cached value if one exists and it's from the same shadow tree
if (parentNode._inDisabledFieldset !== undefined) {
fieldsetDisabled = parentNode._inDisabledFieldset;
break;
}

if (
parentNode.props.nodeName === 'fieldset' &&
parentNode.hasAttr('disabled')
) {
fieldsetDisabled = true;
}
parentNode = parentNode.parent;
}

// cache whether each element turned out to be in a disabled fieldset so we only have to look at each element once
ancestors.forEach(
ancestor => (ancestor._inDisabledFieldset = fieldsetDisabled)
);
if (fieldsetDisabled) {
return true;
}

if (vNode.props.nodeName !== 'area') {
// if the virtual node does not have an actual node, treat it
// as not hidden
if (!vNode.actualNode) {
return false;
}

return isHiddenWithCSS(vNode.actualNode);
}

Expand Down
45 changes: 45 additions & 0 deletions test/checks/keyboard/focusable-disabled.js
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,51 @@ describe('focusable-disabled', function() {
assert.isTrue(actual);
});

it('returns true when content made unfocusable through disabled fieldset', function() {
var params = checkSetup(
'<fieldset id="target" disabled aria-hidden="true"><input /></fieldset>'
);
var actual = check.evaluate.apply(checkContext, params);
assert.isTrue(actual);
});

(shadowSupported ? it : xit)(
'returns false when content is in a disabled fieldset but in another shadow tree',
function() {
var fieldset = document.createElement('fieldset');
fieldset.setAttribute('disabled', 'true');
fieldset.setAttribute('aria-hidden', 'true');
fieldset.setAttribute('id', 'target');
var disabledInput = document.createElement('input');
fieldset.appendChild(disabledInput);
var shadowRoot = document.createElement('div');
fieldset.appendChild(shadowRoot);
var shadow = shadowRoot.attachShadow({ mode: 'open' });
shadow.innerHTML = '<label>Shadow input <input /></label>';
var params = checkSetup(fieldset);

var actual = check.evaluate.apply(checkContext, params);

assert.isFalse(actual);
}
);

it('returns false when content is in the legend of a disabled fieldset', function() {
var params = checkSetup(
'<fieldset id="target" disabled aria-hidden="true"><legend><input /></legend></fieldset>'
);
var actual = check.evaluate.apply(checkContext, params);
assert.isFalse(actual);
});

it('returns false when content is in an aria-hidden but not disabled fieldset', function() {
var params = checkSetup(
'<fieldset id="target" aria-hidden="true"><input /></fieldset>'
);
var actual = check.evaluate.apply(checkContext, params);
assert.isFalse(actual);
});

it('returns true when focusable off screen link (cannot be disabled)', function() {
var params = checkSetup(
'<div id="target" aria-hidden="true"><a href="/" style="position:absolute; top:-999em">Link</a></div>'
Expand Down

0 comments on commit 0865bd7

Please sign in to comment.