Skip to content

Commit 3e53cf4

Browse files
Fix keyboard focus loss during same-month navigation in inline mode
When using selectsRange, inline, and showPreviousMonths with a mismatched openToDate vs startDate, keyboard navigation within the same month would fail to properly transfer focus to the new day element. The root cause was that shouldFocusDayInline was set to false when navigating within the same month, which prevented the Day component from receiving focus. Since keyboard navigation is always user- initiated from a focused day, the destination day should always receive focus. This change simplifies the inline mode focus logic to always set shouldFocusDayInline to true during keyboard navigation, ensuring focus is properly transferred regardless of whether the month changed. Fixes #5750 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]>
1 parent 877403c commit 3e53cf4

File tree

2 files changed

+56
-15
lines changed

2 files changed

+56
-15
lines changed

src/index.tsx

Lines changed: 5 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1392,20 +1392,12 @@ export class DatePicker extends Component<DatePickerProps, DatePickerState> {
13921392
this.setSelected(newSelection);
13931393
}
13941394
this.setPreSelection(newSelection);
1395-
// need to figure out whether month has changed to focus day in inline version
1395+
// In inline mode, always set shouldFocusDayInline to true when navigating via keyboard.
1396+
// This ensures focus is properly transferred to the new day element regardless of
1397+
// whether the month changed. The user initiated this navigation from a focused day,
1398+
// so we should always focus the destination day.
13961399
if (inline) {
1397-
const prevMonth = getMonth(copy);
1398-
const newMonth = getMonth(newSelection);
1399-
const prevYear = getYear(copy);
1400-
const newYear = getYear(newSelection);
1401-
1402-
if (prevMonth !== newMonth || prevYear !== newYear) {
1403-
// month has changed
1404-
this.setState({ shouldFocusDayInline: true });
1405-
} else {
1406-
// month hasn't changed
1407-
this.setState({ shouldFocusDayInline: false });
1408-
}
1400+
this.setState({ shouldFocusDayInline: true });
14091401
}
14101402
};
14111403

src/test/datepicker_test.test.tsx

Lines changed: 51 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3851,7 +3851,7 @@ describe("DatePicker", () => {
38513851
describe("shouldFocusDayInline state", () => {
38523852
const dateFormat = "yyyy-MM-dd";
38533853

3854-
it("should not be updated when navigating with ArrowRight key without changing displayed month", () => {
3854+
it("should be set to true when navigating with ArrowRight key without changing displayed month", () => {
38553855
let instance: DatePicker | null = null;
38563856
const { container } = render(
38573857
<DatePicker
@@ -3867,7 +3867,8 @@ describe("DatePicker", () => {
38673867
expect(selectedDayNode).toBeTruthy();
38683868
fireEvent.keyDown(selectedDayNode!, getKey(KeyType.ArrowRight));
38693869
expect(instance).toBeTruthy();
3870-
expect(instance!.state.shouldFocusDayInline).toBe(false);
3870+
// Always set to true for keyboard navigation to ensure focus transfers correctly
3871+
expect(instance!.state.shouldFocusDayInline).toBe(true);
38713872
});
38723873

38733874
it("should be set to true when changing displayed month with ArrowRight key", () => {
@@ -3907,6 +3908,54 @@ describe("DatePicker", () => {
39073908
expect(instance).toBeTruthy();
39083909
expect(instance!.state.shouldFocusDayInline).toBe(true);
39093910
});
3911+
3912+
it("should maintain keyboard focus when navigating within same month in inline selectsRange mode with showPreviousMonths", () => {
3913+
// This test verifies the fix for GitHub issue #5750
3914+
// Focus was being lost when navigating within the same month in inline mode
3915+
// with selectsRange and showPreviousMonths enabled
3916+
const startDate = newDate("2025-06-01");
3917+
const endDate = newDate("2025-07-01");
3918+
const div = document.createElement("div");
3919+
document.body.appendChild(div);
3920+
3921+
const { container } = render(
3922+
<DatePicker
3923+
selectsRange
3924+
inline
3925+
showPreviousMonths
3926+
monthsShown={2}
3927+
startDate={startDate}
3928+
endDate={endDate}
3929+
openToDate={endDate}
3930+
/>,
3931+
{ container: div },
3932+
);
3933+
3934+
// Find the start date (June 1) and focus it
3935+
const startDateNode = container.querySelector(
3936+
'.react-datepicker__day--range-start[tabindex="0"]',
3937+
);
3938+
expect(startDateNode).toBeTruthy();
3939+
act(() => {
3940+
(startDateNode as HTMLElement)?.focus();
3941+
});
3942+
expect(document.activeElement).toBe(startDateNode);
3943+
3944+
// Navigate right (to June 2, same month)
3945+
fireEvent.keyDown(startDateNode!, getKey(KeyType.ArrowRight));
3946+
3947+
// After navigation, focus should be on June 2, not lost to body
3948+
const newFocusedDay = container.querySelector(
3949+
'.react-datepicker__day[tabindex="0"]',
3950+
);
3951+
expect(newFocusedDay).toBeTruthy();
3952+
expect(document.activeElement).not.toBe(document.body);
3953+
expect(
3954+
document.activeElement?.classList.contains("react-datepicker__day"),
3955+
).toBe(true);
3956+
3957+
document.body.removeChild(div);
3958+
});
39103959
});
39113960

39123961
describe("Calendar Header Accessibility", () => {

0 commit comments

Comments
 (0)