-
Notifications
You must be signed in to change notification settings - Fork 470
feat(byRole): Exclude inaccessible elements #352
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat(byRole): Exclude inaccessible elements #352
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looking good. A few things. Also it looks like we're missing some tests and we should add this to all of the queries.
src/__tests__/role.js
Outdated
expect(() => getByRole('list')).toThrowErrorMatchingInlineSnapshot(` | ||
"Unable to find an accessible element with the role "list" | ||
|
||
There are no accessible roles. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should probably add something to this message that says: "But there are some inaccessible roles. If you wish to access them, then set the hidden option to true. Learn more about this here: linktodocs.com"
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This would require a lot of refactoring if we want to actually determine if there are hidden roles.
Would it be sufficient to say "There might be inaccessible roles" instead?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Extended the message and added a link to the docs but didn't implement displaying accessible vs. inaccessible roles. I think this isn't required to get this merged but I would like to see this at some point as well.
|
||
${roles.replace(/\n/g, '\n ').replace(/\n\s\s\n/g, '\n\n')} | ||
`.trim() | ||
} | ||
|
||
return ` | ||
Unable to find an element with the role "${role}" | ||
Unable to find an ${ | ||
hidden === false ? 'accessible ' : '' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Remove the extra space.
hidden === false ? 'accessible ' : '' | |
hidden === false ? 'accessible' : '' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think I need to keep this and remove the unconditional space later on. Otherwise we get
Unable to find an element with the role "${role}
^^ double space
for hidden: false
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Extra space is still there (since I'm pretty sure it's required) but I fixed the double space issue.
950c779
to
3f5debb
Compare
b3fe775
to
7cdfcfa
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm good with this. Just one thing.
src/role-helpers.js
Outdated
|
||
let currentElement = element | ||
while (currentElement !== null) { | ||
if (currentElement.hasAttribute('hidden')) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is it permissible to have hidden="false"
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This would also be considered hidden. I should use the property here since it does not require knowledge of attributes vs. properties. You can also check this in your user agent's default stylesheet which should have
[hidden] {
display: none;
}
This is only a recommendation though so we rely on the hidden
attribute definition:
The hidden attribute is a boolean attribute.
-- https://html.spec.whatwg.org/multipage/interaction.html#dom-hidden
The presence of a boolean attribute on an element represents the true value, and the absence of the attribute represents the false value.
-- https://html.spec.whatwg.org/multipage/common-microsyntaxes.html#boolean-attribute
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would be interesting to see what react does with boolean attributes. It would be nice if it would add a warning since hidden="false"
does not work as one might expect.
And it does:
Warning: Received the string
false
for the boolean attributehidden
. The browser will interpret it as a truthy value. Did you mean hidden={false}?
I'm happy with this. Thank you! |
🎉 This PR is included in version 6.4.0 🎉 The release is available on:
Your semantic-release bot 📦🚀 |
Unfamiliar with semantic-release: Should I have used another message format or was this intended to be a feature release? |
I set the commit message when I use "Rebase & Merge." I intended this to be a feature release because I consider it highly unlikely to break anyone's existing tests. I'll take the brunt of any anger or frustration if I'm wrong. |
I do think a breaking change should have been a major version. I somehow picked this up with a new lockfile. My breaking case is that I have a table with a scrolling body which essentially created two headers, one that is visible and one that is sr-only. The strategy is arguable. EIther way, I was used to finding both sets of |
If this means "screen-reader only" then this is either a bug on our side or it detected an actual issue inside your markup. Could you share your markup + style that you would consider screen-reader only? This function should implement specification from the W3C which is either already implemented in assistive technology or will be. |
Apologies, I meant "one that is visible and aria-hidden and one that is sr-only". The changes in this PR appear to be working fine. My point is that I did have tests that broke because of this PR. |
Well as kent said
😄 |
Is there a reason this doesn't exist for |
BREAKING
Certain1 elements will no longer be included in
byRole
queries.Examples:
<ul hidden />
will no longer by included in*byRole('list')
<main aria-hidden="true"><ul /><main>
will no longer return an element in*byRole('list')
orgetByRole('main')
What:
Implement https://www.w3.org/TR/core-aam-1.1/#exclude_elements2 with the following deviation:
role="none"
androle="presentation"
is included (not followingMUST
criteria)I feel like this is more of a concern for an actual a11y tree implementation.
getByRole('presentation')
not returning anything even if the element is visible is probably confusing but I could see us throwing an error here. We could argue that one should usegetByTestId
instead since this makes it obvious you're not querying the a11y tree.SHOULD
criteria)Why:
Closes #350
How:
Implementation is kept simple and mirrors the spec. Faster implementation is considered for a future PR.
Checklist:
docs site Will do once this is approved
[ ] Typescript definitions updatedSeparate type PR is preparedI'm open to removing the option and making it default. In any case it should be released in a breaking change since it is potentially breaking.
1 excluded are elements that
aria-hidden=true
or any of its ancestorshidden
attribute or any of its ancestorsdisplay: none
or any of its ancestorshidden
as their computedvisibility