Skip to content

Commit

Permalink
Merge pull request #5011 from qburst/issue-5010/fix/initial-disabled-…
Browse files Browse the repository at this point in the history
…date-focus

Fix #5010: 🐛 Restrict the focus to the disabled months/quarter/year using the initial Tab key navigation
  • Loading branch information
martijnrusschen authored Jul 29, 2024
2 parents 682b1cc + 6df7994 commit 438092d
Show file tree
Hide file tree
Showing 5 changed files with 157 additions and 5 deletions.
14 changes: 12 additions & 2 deletions src/month.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -843,8 +843,12 @@ export default class Month extends Component<MonthProps> {
return "-1";
}
const preSelectedMonth = getMonth(this.props.preSelection);
const { isDisabled: isPreSelectedMonthDisabled } =
this.isMonthDisabledForLabelDate(preSelectedMonth);

const tabIndex =
!this.props.disabledKeyboardNavigation && m === preSelectedMonth
m === preSelectedMonth &&
!(isPreSelectedMonthDisabled || this.props.disabledKeyboardNavigation)
? "0"
: "-1";

Expand All @@ -856,8 +860,14 @@ export default class Month extends Component<MonthProps> {
return "-1";
}
const preSelectedQuarter = getQuarter(this.props.preSelection);
const isCurrentQuarterDisabled = isQuarterDisabled(
this.props.day,
this.props,
);

const tabIndex =
!this.props.disabledKeyboardNavigation && q === preSelectedQuarter
q === preSelectedQuarter &&
!(isCurrentQuarterDisabled || this.props.disabledKeyboardNavigation)
? "0"
: "-1";

Expand Down
83 changes: 82 additions & 1 deletion src/test/month_test.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ import {
import Month from "../month";

import { runAxe } from "./run_axe";
import { getKey, range } from "./test_utils";
import { getKey, range, openDateInput, gotoNextView } from "./test_utils";

import type { RenderResult } from "@testing-library/react";

Expand Down Expand Up @@ -2525,4 +2525,85 @@ describe("Month", () => {
).toBeNull();
});
});

describe("Auto-Focus", () => {
it("should auto-focus on the same selected month when navigating to the next/previous year", () => {
const date = newDate("2024-06-01");
const selectedMonth = date.getMonth();

const { container } = render(
<DatePicker selected={date} showMonthYearPicker />,
);

openDateInput(container);
gotoNextView(container);

const preSelectedDateElement = container.querySelector(
`.react-datepicker__month-text.react-datepicker__month-${selectedMonth}`,
)!;
expect(preSelectedDateElement.getAttribute("tabindex")).toBe("0");
});

it("shouldn't auto-focus on the same selected month when navigating to the next/previous year if the corresponding month is disabled", () => {
const date = newDate("2024-06-01");
const selectedMonth = date.getMonth();
const excludeDate = newDate(`2025-0${selectedMonth + 1}-01`);

const { container } = render(
<DatePicker
selected={date}
showMonthYearPicker
excludeDates={[excludeDate]}
/>,
);

openDateInput(container);
gotoNextView(container);

const preSelectedDateElement = container.querySelector(
`.react-datepicker__month-text.react-datepicker__month-${selectedMonth}`,
)!;
expect(preSelectedDateElement.getAttribute("tabindex")).toBe("-1");
});

it("should auto-focus on the same selected quarter when navigating to the next/previous year", () => {
const date = newDate("2024-06-01");

const { container } = render(
<DatePicker selected={date} showQuarterYearPicker />,
);

openDateInput(container);
const selectedQuarterValue = getQuarter(date);
gotoNextView(container);

const preSelectedDateElement = container.querySelector(
`.react-datepicker__quarter-text.react-datepicker__quarter-${selectedQuarterValue}`,
)!;
expect(preSelectedDateElement.getAttribute("tabindex")).toBe("0");
});

it("shouldn't auto-focus on the same selected quarter when navigating to the next/previous year if the corresponding quarter date is disabled", () => {
const date = newDate("2024-06-01");
const selectedMonth = date.getMonth();
const excludeDate = newDate(`2025-0${selectedMonth + 1}-01`);

const { container } = render(
<DatePicker
selected={date}
showQuarterYearPicker
excludeDates={[excludeDate]}
/>,
);

openDateInput(container);
const selectedQuarterValue = getQuarter(date);
gotoNextView(container);

const preSelectedDateElement = container.querySelector(
`.react-datepicker__quarter-text.react-datepicker__quarter-${selectedQuarterValue}`,
)!;
expect(preSelectedDateElement.getAttribute("tabindex")).toBe("-1");
});
});
});
15 changes: 15 additions & 0 deletions src/test/test_utils.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { fireEvent } from "@testing-library/react";

import { KeyType } from "../date_utils";

interface KeyEvent {
Expand Down Expand Up @@ -65,3 +67,16 @@ export const range = (from: number, to: number): number[] => {
}
return list;
};

export const openDateInput = (container: Element) => {
const dateInput = container.querySelector("input")!;
fireEvent.focus(dateInput);
};

export const gotoNextView = (container: Element) => {
const calendar = container.querySelector(".react-datepicker")!;
const nextButton = calendar.querySelector(
".react-datepicker__navigation--next",
)!;
fireEvent.click(nextButton);
};
47 changes: 46 additions & 1 deletion src/test/year_picker_test.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,15 @@ import {
import DatePicker from "../index";
import Year from "../year";

import { getKey } from "./test_utils";
import { getKey, gotoNextView, openDateInput } from "./test_utils";

const getYearOffset = (calendar: Element, date: Date): number => {
const dateNode = calendar.querySelector(
`.react-datepicker__year-text.react-datepicker__year-${date.getFullYear()}`,
)!;
const yearPicker = calendar.querySelector(".react-datepicker__year-wrapper")!;
return Array.from(yearPicker.children).indexOf(dateNode);
};

describe("YearPicker", () => {
it("should show year picker component when showYearPicker prop is present", () => {
Expand Down Expand Up @@ -872,4 +880,41 @@ describe("YearPicker", () => {
container.querySelector(`.react-datepicker__year-${date.getFullYear()}`),
).not.toBeNull();
});

describe("Auto-Focus", () => {
it("should auto-focus on the same year offset in the next/previous view when navigating", () => {
const date = newDate("2024-06-01");
const { container } = render(
<DatePicker selected={date} showYearPicker dateFormat="yyyy" />,
);
openDateInput(container);
const calendar = container.querySelector(".react-datepicker")!;
const selectedElementOffset = getYearOffset(calendar, date);
gotoNextView(container);
const preSelectedDateElement = container.querySelector(
`.react-datepicker__year-wrapper :nth-child(${selectedElementOffset + 1}).react-datepicker__year-text`,
)!;
expect(preSelectedDateElement.getAttribute("tabindex")).toBe("0");
});
it("shouldn't auto-focus on the same year offset in the next/previous view when navigating if the year in the corresponding offset is disabled", () => {
const date = newDate("2024-06-01");
const excludeDate = newDate("2036-05-01"); // 2036 is in the same 8th offset like 2024
const { container } = render(
<DatePicker
selected={date}
excludeDates={[excludeDate]}
showYearPicker
dateFormat="yyyy"
/>,
);
openDateInput(container);
const calendar = container.querySelector(".react-datepicker")!;
const selectedElementOffset = getYearOffset(calendar, date);
gotoNextView(container);
const preSelectedDateElement = container.querySelector(
`.react-datepicker__year-wrapper :nth-child(${selectedElementOffset + 1}).react-datepicker__year-${excludeDate.getFullYear()}`,
)!;
expect(preSelectedDateElement.getAttribute("tabindex")).toBe("-1");
});
});
});
3 changes: 2 additions & 1 deletion src/year.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -402,8 +402,9 @@ export default class Year extends Component<YearProps> {
return "-1";
}
const preSelected = getYear(this.props.preSelection);
const isPreSelectedYearDisabled = isYearDisabled(y, this.props);

return y === preSelected ? "0" : "-1";
return y === preSelected && !isPreSelectedYearDisabled ? "0" : "-1";
};

getYearContainerClassNames = () => {
Expand Down

0 comments on commit 438092d

Please sign in to comment.