Skip to content

Commit c7e4e3d

Browse files
fix: restore sr-only pattern for weekday headers accessibility
The previous change broke axe accessibility tests by using aria-label instead of the sr-only span pattern. Screen readers need visible text content in columnheader elements, not just aria-hidden spans. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]>
1 parent b392371 commit c7e4e3d

File tree

3 files changed

+19
-20
lines changed

3 files changed

+19
-20
lines changed

src/calendar.tsx

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -488,8 +488,8 @@ export default class Calendar extends Component<CalendarProps, CalendarState> {
488488
key="W"
489489
className={`react-datepicker__day-name ${disabled ? "react-datepicker__day-name--disabled" : ""}`}
490490
role="columnheader"
491-
aria-label="Week number"
492491
>
492+
<span className="react-datepicker__sr-only">Week number</span>
493493
<span aria-hidden="true">{this.props.weekLabel || "#"}</span>
494494
</div>,
495495
);
@@ -507,13 +507,15 @@ export default class Calendar extends Component<CalendarProps, CalendarState> {
507507
<div
508508
key={offset}
509509
role="columnheader"
510-
aria-label={formatDate(day, "EEEE", this.props.locale)}
511510
className={clsx(
512511
"react-datepicker__day-name",
513512
weekDayClassName,
514513
disabled ? "react-datepicker__day-name--disabled" : "",
515514
)}
516515
>
516+
<span className="react-datepicker__sr-only">
517+
{formatDate(day, "EEEE", this.props.locale)}
518+
</span>
517519
<span aria-hidden="true">{weekDayName}</span>
518520
</div>
519521
);

src/test/calendar_test.test.tsx

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2297,13 +2297,11 @@ describe("Calendar", () => {
22972297

22982298
const header = container.querySelector(".react-datepicker__header");
22992299
const dayNameElements = header?.querySelectorAll(
2300-
".react-datepicker__day-name",
2300+
".react-datepicker__day-name > span.react-datepicker__sr-only",
23012301
);
23022302

23032303
dayNameElements?.forEach((element, index) => {
2304-
expect(element.getAttribute("aria-label")).toBe(
2305-
expectedAriaLabels[index],
2306-
);
2304+
expect(element.textContent).toBe(expectedAriaLabels[index]);
23072305
});
23082306
});
23092307

src/test/datepicker_test.test.tsx

Lines changed: 13 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -3829,7 +3829,7 @@ describe("DatePicker", () => {
38293829
});
38303830

38313831
describe("Calendar Header Accessibility", () => {
3832-
it("renders day names with aria-label full weekday and visible short name", () => {
3832+
it("renders day names with react-datepicker__sr-only full weekday and visible short name", () => {
38333833
const { container } = render(<DatePicker />);
38343834
const input = safeQuerySelector(container, "input");
38353835
fireEvent.focus(input);
@@ -3840,20 +3840,19 @@ describe("DatePicker", () => {
38403840
expect(headers.length).toBe(7);
38413841

38423842
headers.forEach((header) => {
3843-
// Should have an aria-label with the full weekday name
3844-
const ariaLabel = header?.getAttribute("aria-label");
3845-
expect(ariaLabel?.length).toBeGreaterThan(2);
3843+
// Should have a visually hidden span with the full weekday name
3844+
const srOnly = header.querySelector(".react-datepicker__sr-only");
3845+
expect(srOnly).toBeTruthy();
3846+
expect(srOnly?.textContent?.length).toBeGreaterThan(2);
38463847

38473848
// Should have a visible short name
3848-
const visible = header.querySelector(
3849-
'.react-datepicker__day-name > span[aria-hidden="true"]',
3850-
);
3849+
const visible = header.querySelector('span[aria-hidden="true"]');
38513850
expect(visible).toBeTruthy();
38523851
expect(visible?.textContent?.length).toBeLessThanOrEqual(3);
38533852
});
38543853
});
38553854

3856-
it("renders week number column header with aria-label and visible #", () => {
3855+
it("renders week number column header with react-datepicker__sr-only label and visible #", () => {
38573856
const { container } = render(<DatePicker showWeekNumbers />);
38583857
const input = safeQuerySelector(container, "input");
38593858
fireEvent.focus(input);
@@ -3864,15 +3863,15 @@ describe("DatePicker", () => {
38643863
expect(headers.length).toBe(8);
38653864

38663865
const weekNumberHeader = headers[0] as Element;
3867-
expect(weekNumberHeader).toBeTruthy();
3868-
3869-
// Should have aria-label = "Week number"
3870-
const ariaLabel = weekNumberHeader?.getAttribute("aria-label");
3871-
expect(ariaLabel?.trim()?.toLowerCase()).toEqual("week number");
3866+
const srOnly = weekNumberHeader.querySelector(
3867+
".react-datepicker__sr-only",
3868+
);
3869+
expect(srOnly).toBeTruthy();
3870+
expect(srOnly?.textContent?.trim()?.toLowerCase()).toEqual("week number");
38723871

38733872
// Should have a visible short name
38743873
const visible = weekNumberHeader.querySelector(
3875-
'.react-datepicker__day-name > span[aria-hidden="true"]',
3874+
'span[aria-hidden="true"]',
38763875
);
38773876
expect(visible).toBeTruthy();
38783877
expect(visible?.textContent?.trim()?.toLowerCase()).toEqual("#");

0 commit comments

Comments
 (0)