-
-
Notifications
You must be signed in to change notification settings - Fork 727
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
Add ARIA attributes for better accessibility #33
Comments
@basham thanks for taking the time to write this, it is really helpful 👍. Many suggestions are trivial to implement (see unit test below). For supporting
let captionElements = getElementsByClassName(dayPickerNode, "DayPicker-Caption");
let monthElements = getElementsByClassName(dayPickerNode, "DayPicker-Month");
let weekdaysElements = getElementsByClassName(dayPickerNode, "DayPicker-Weekdays");
let weekdayElements = getElementsByClassName(dayPickerNode, "DayPicker-Weekday");
let bodyElements = getElementsByClassName(dayPickerNode, "DayPicker-Body");
let weekElements = getElementsByClassName(dayPickerNode, "DayPicker-Week");
let dayElements = getElementsByClassName(dayPickerNode, "DayPicker-Day");
expect(dayPickerNode.getAttribute("role")).to.equal("widget");
expect(monthElements.every(el => el.getAttribute("role") === "grid")).to.be.true;
expect(monthElements.every(el => el.getAttribute("aria-readonly"))).to.equal("true");
monthElements.forEach((el, i) => {
let captionId = captionElements[i].getAttribute("id");
expect(el.getAttribute("aria-labelledby")).to.equal(captionId);
});
expect(weekdaysElements.every(el => el.getAttribute("role"))).to.equal("rowgroup");
expect(weekdayElements.every(el => el.getAttribute("role") === "columnheader")).to.be.true;
expect(bodyElements.every(el => el.getAttribute("role") === "rowgroup")).to.be.true;
expect(weekElements.every(el => el.getAttribute("role") === "row")).to.be.true;
expect(dayElements.every(el => el.getAttribute("role") === "gridcell")).to.be.true; |
Figured most of these suggestions would be really easy to implement. Thanks for the quick work on this. I also assumed that |
I retract my suggestion of having Since you're already managing focus on widget descendants, it's probably best to just leave the code as-is. Additionally, focus is a more established feature than References |
Would be happy to test a PR with a screen-reader. |
I'm sure you know already, but you can easily test the compliance here: https://validator.w3.org/nu/#textarea At the moment it's the only thing stopping our site from passing WCAG AA, so looking forward to this one! (BTW, great component) |
Hi @davidgilbertson yes thank you for the link! |
If I am able to get this change set up as a task in my project, would you consider a pull request? |
I would really appreciate any help, @davidgilbertson! |
OK it looks like I can get this as a task in my next sprint. To be clear I plan to fix these three issues thrown by the w3 validator:
Should come up a few weeks from now. |
I'm interested, what is |
OMG @davidgilbertson I think that |
Happens to the best of us. :) |
Hi! This is just to say that my project has really appreciate this react-day-picker, and we're looking forward to improvements in accessibility. One of my colleagues uses a screen reader, and cannot use the calendar in our app. There are, in particular, two issues for screen readers:
Echoing @ezufelt above, I'm happy to help test any patches that might fix those issues. |
Thanks @ragesoss! There's a PR from @limscoder that may add some improvements for ARIA, but I'm not sure if it fixes all the issues. Going to check it out soon. |
FWIW... After thinking about this for a while, if I couldn't see (or was a keyboard navigator), I would much rather just type a date than navigate a calendar, so we are aria-hiding the calendar and just having an input field to type date. |
@davidgilbertson That makes sense for picking a single date — I know that's what my colleague Helaine prefers when it's a matter of one date — but will it work for a calendar that is being used to select multiple dates? In my app, we use it with three states and lots of selected dates at once. |
@davidgilbertson I work for Indiana University, and consulting with our assistive technologies team, they say the same thing. A text input is much simpler to use for a keyboard user. And a text input is much easier to understand for those navigating with only a screen reader. Assuming that's the case and assuming the intention is to select one date at a time, I think it's less imperative that this date picker can be controlled with a keyboard. I think we need to think about what is the best way to provide equivalent controls with a text input. Perhaps this text control is another project. Maybe it is a sub-component of this project. My current thought is that Facebook's date input for events is a rather fantastic exemplar. The up/down arrow keys toggles through the month/day/year based on the placement of the keyboard cursor, providing very quick non-calendar-based input. |
@ragesoss is right saying that for multiple days input fields would not be enough. There are already three pull requests (two of them are rather old) waiting to be analyzed and merged. It seems, however, they require a good amount of work 😅 I'm committed to work again on this soon! |
While
react-day-picker
works with the keyboard, its semantics could be improved by adding the appropriate ARIA attributes, so screen readers will better interpret how the component works.Probably the best React exemplar I've found which achieves this nicely is
react-widgets
Calendar. However, I see the customizability of thereact-day-picker
project being much more ideal. I really like the clean, small ES6 implementation with no dependencies outside of React.The following are some suggestions based on my research. Some suggestions are a result of adding back certain semantics which were lost due to switching from
<table>
to<div>
. Suggestions are organized by the element to which it affects, identified by its class name..DayPicker-Month
role="grid"
attribute; grid cells need an ancestorgrid
.aria-readonly="true"
attribute to indicate that the child grid cells will never be edited; by default, grid cells are assumed to be editable.aria-labelledby
attribute to explicitly indicate the.DayPicker-Caption
element is labeling the month grid.aria-activedescendant
attribute to explicitly indicate which.DayPicker-Day
is in focus..DayPicker-Caption
.DayPicker-Month
enhancements..DayPicker-Weekdays
role="rowgroup"
attribute, which is equivalent to using<thead>
element..DayPicker-Weekday
role="columnheader"
attribute, which is equivalent to using the<th>
element..DayPicker-Body
role="rowgroup"
attribute, which is equivalent to using<tbody>
element..DayPicker-Day
.DayPicker-Month
enhancements.aria-disabled="true|false"
attribute to indicate if the cell is selectable; this suggests that not every day within a given range of dates has to be selectable.aria-selected="true|false"
attribute to indicate if the cell is selected.title="Today"
attribute to a day which is today; if not wanting the tooltip to appear, then usearia-label="Today"
attribute. Alternatively, this suggestion could be implemented via a custom day component, rather than in this project.Additional considerations
Since
aria-labelledby
andaria-activedescendant
reference an id, it may be good to dynamically generate unique ids for elements they reference, so you avoid the problem of having different instances ofreact-day-picker
accidentally cross-reference each other.The text was updated successfully, but these errors were encountered: