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
a11y: fix wrong role for day button #1708
base: main
Are you sure you want to change the base?
Conversation
a039e1f
to
e6e658e
Compare
Hey thanks a lot for your contribution. Before changing the role, I'd like to add more accessibility tests - so please have patience before we merge this. BTW, do you know some best practice to test the screen readers? |
@gpbl No worries - Sadly I don't know of a way to automate screen reader tests. |
…-day-picker into pr/Kosai106/1708 # Conflicts: # website/test/axe.ts
OK @Kosai106 I could add the aXe tests for website. Now that the role is |
@@ -107,7 +107,7 @@ export function useDayRender( | |||
const buttonProps = { | |||
...divProps, | |||
disabled: activeModifiers.disabled, | |||
role: 'gridcell', | |||
role: 'button', |
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 believe this will break accessibility in some ways because button
elements are not supposed to be children of grid > rowgroup
. I would recommend testing any changes with a screen reader.
I've found that the structure that makes the most sense is to add a div
with the role of gridcell
and the button
inside the gridcell
. Additionally, using the aria-pressed
attribute for the button when it is selected (since aria-selected
is not valid attribute for button
elements, and simply having aria-selected
in the gridcell
did not work in VoiceOver. [as in, it didn't announce that the day was selected]). Adding aria-pressed
changes the buttons to toggle
buttons, which seems appropriate since a date is either selected or not selected.
So
<table role="grid">
<!-- OMITTED HEAD -->
<tbody role="rowgroup">
<tr>
<td role="presentation">
<div role="gridcell">
<button name="day" aria-label="April 1st, 2022" aria-pressed="false" tabindex="0" type="button">1</button>
</div>
</td>
<!-- !! SELECTED STATE -->
<td role="presentation">
<div role="gridcell" aria-selected="true">
<button name="day" aria-label="April 1st, 2022" aria-pressed="true" tabindex="0" type="button">1</button>
</div>
</td>
</tr>
</tbody>
</table>
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.
You can possibly consider removing the div
and changing role="presentation"
to role="gridcell"
in the td
element. But please test in a screen reader.
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.
@GeorgeTaveras1231 thanks for your feedback here. Screen readers do read better the calendar when overriding roles, but the aXe test that doesn't like that.
I believe the correct HTML is to render a grid with grid cells being clickable, focusable, and "aria-selected". However, for some old design choices, we have now a button instead of a grid cell. Not easy to change the underlying HTML without introducing breaking changes.
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.
@gpbl 🤔 I have doubts about this approach. From my research it seems gridcell
elements are grouping elements (except when the content is editable [think spreadsheet, for example]). In which case, clicking on the cells is just used to focus on the cell to allow the user to type. The way in which the DayPicker
works, each Day behaves as a toggle button. Clicking on it, toggles the selected/unselected state. A gridcell
by itself wont be able to communicate the sort of interactions each Day supports, as well as a toggle button can.
I also looked at the ARIA role hierarchy to support this point, where you can see interactive elements generally stem from the abstract widget
role. There you'll see the button
role, whereas the gridcell
role inherits from section
, which is a structure
role, and is mainly for grouping content.
Resources:
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.
Additionally you can consider making each day a checkbox
or radio
depending on the mode
(single
-> radio
; multiple
-> checkbox
) 💡
Context
Fixes #1688 by changing the button role to the correct
button
role rather thangridcell
.Also adds
aria-hidden="true"
on the hidden gridcell div.Analysis
See GitHub issue: #1688
Solution
See "Context" section.