Skip to content
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

[Bug]: Accessibility: The aria-expanded attribute should always be rendered #580

Closed
afercia opened this issue Jun 1, 2021 · 4 comments
Closed

Comments

@afercia
Copy link
Contributor

afercia commented Jun 1, 2021

What package within Headless UI are you using?

@headlessui/react

What version of that package are you using?

v1.2.0

What browser are you using?

N/A

Reproduction repository

Your Disclosure demo at https://headlessui.dev/react/disclosure

Describe your issue

First of all, thanks for your hard work on Headless UI!

While using the Disclosure component, our team noticed a behavior related to the aria-expanded attribute that isn't entirely correct and can be improved for better accessibility.

When the Disclosure is open, aria-expanded is added to the Disclosure.Button with a value of true, which is correct. However, when the Disclosure is closed, aria-expanded is not rendered at all.

I guess this applies also to other components where aria-expanded is used.

This happens for both the react version and the vue version.

Basically, using an undefined value makes the attribute be omitted from the DOM:

'aria-expanded': state.disclosureState === DisclosureStates.Open ? true : undefined,

Instead, it should be set to false.

I do realize that in a react/vue world is pretty common to not render HTML attributes when their value is false, however aria-expanded isn't a HTML boolean attribute. aria-expanded represents a state that is either "collapsed" or "expanded" and it must be always rendered. It also has to do with the way screen readers announce aria-expanded:

  • aria-expanded=true is announced as "expanded"
  • aria-expanded=false is announced as "collapsed"

Not rendering aria-expanded when false doesn't provide a correct information to screen reader users: they won't have a clue there's something that can be expanded and it’s currently “collapsed”.

Quoting from the WAI-ARIA Authoring Practices Disclosure pattern, see the "WAI-ARIA Roles, States, and Properties" section:

When the content is visible, the element with role button has aria-expanded set to true. When the content area is hidden, it is set to false.

RobinMalfait added a commit that referenced this issue Jun 4, 2021
`aria-expanded` can be in 3 different states:

| Value               | Description                                                                |
| ------------------- | -------------------------------------------------------------------------- |
| false               | The grouping element this element owns or controls is collapsed.           |
| true                | The grouping element this element owns or controls is expanded.            |
| undefined (default) | The element does not own or control a grouping element that is expandable. |

Ref: https://www.w3.org/TR/wai-aria-1.2/#aria-expanded

Fixes: #580
@RobinMalfait
Copy link
Collaborator

RobinMalfait commented Jun 4, 2021

Hey! Thank you for your detailed bug report!
Much appreciated! 🙏

I'm going to fix this all in this PR #592
You are correct that we need to actually output the value "false" and the value "true". The reason why I had the undefined is probably because of some other incorrect values. For example, in the PR you will see a fix for the disabled prop as well. Because in Vue, it was outputted like disabled="false" which is not consistent with React where we omit that value.

I'll close this issue once the PR is ready!

RobinMalfait added a commit that referenced this issue Jun 4, 2021
* encode expected `aria-expanded` behaviour

* ensure `aria-expanded` has the correct value

`aria-expanded` can be in 3 different states:

| Value               | Description                                                                |
| ------------------- | -------------------------------------------------------------------------- |
| false               | The grouping element this element owns or controls is collapsed.           |
| true                | The grouping element this element owns or controls is expanded.            |
| undefined (default) | The element does not own or control a grouping element that is expandable. |

Ref: https://www.w3.org/TR/wai-aria-1.2/#aria-expanded

Fixes: #580

* ensure `disabled` prop in Vue is not rendered when `false`

* update changelog
@afercia
Copy link
Contributor Author

afercia commented Jun 7, 2021

@RobinMalfait thank you for looking into this and for the really quick fix! 🎉
Yep, makes sense to take into account also the disabled prop.

@yvonnetangsu
Copy link

I was going to post the same question for the Popover button, looks like this has been fixed. Awesome. Thank you all.

@RobinMalfait
Copy link
Collaborator

This should be fixed, and will be available in the next release.

  • You can already try it using npm install @headlessui/react@dev or yarn add @headlessui/react@dev.
  • You can already try it using npm install @headlessui/vue@dev or yarn add @headlessui/vue@dev.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants