Skip to content

fix: clamp the displayed month when the navigation range changes - #3006

Open
nahuelsoria wants to merge 1 commit into
gpbl:mainfrom
nahuelsoria:fix/clamp-display-month-on-nav-range-change
Open

fix: clamp the displayed month when the navigation range changes#3006
nahuelsoria wants to merge 1 commit into
gpbl:mainfrom
nahuelsoria:fix/clamp-display-month-on-nav-range-change

Conversation

@nahuelsoria

Copy link
Copy Markdown

Closes #2912.

The problem

When endMonth (or startMonth) changes to a range that no longer contains the month being displayed, the month grid and the dropdowns disappear.

getDisplayMonths breaks out of its loop as soon as the first month is past calendarEndMonth, so it returns an empty array and nothing is rendered:

for (let i = 0; i < numberOfMonths; i++) {
  const month = dateLib.addMonths(firstDisplayedMonth, i);
  if (calendarEndMonth && month > calendarEndMonth) break;
  months.push(month);
}

The displayed month is clamped to the navigation range by getInitialMonth, but that only happens when the calendar mounts (and when the time zone changes). The month stored by useControlledValue is then left out of range.

Worth noting: this does not reproduce when month is controlled, because in that case initialMonth is recomputed on every render and the clamping is applied again. The uncontrolled case was the one drifting out of range.

The fix

Clamp the displayed month to the navigation range on every render, reusing the existing getInitialMonth logic so the rule lives in one place:

const displayMonth = getInitialMonth(
  { ...props, month: firstMonth },
  navStart,
  navEnd,
  dateLib,
);

displayMonth then feeds getDisplayMonths, getPreviousMonth and getNextMonth, so the grid, the dropdowns and the navigation buttons all stay consistent with the new range. This matches the behaviour suggested in the issue: the calendar switches to the closest month it can display. No state is written, so no extra render and no onMonthChange is fired.

Tests

Three tests in DayPicker.test.tsx covering endMonth narrowing, startMonth moving forward, and numberOfMonths={2}. They fail on main and pass with the fix.

Verification

  • pnpm test: 221 suites, 1087 tests passing
  • pnpm test:tz: 3 passing
  • pnpm typecheck and biome check: clean
  • Same results on main before the change, so no regressions

When `startMonth` or `endMonth` changed after the calendar had been
rendered, the stored month was left outside the navigation range:
`getDisplayMonths` then returned no months, so the month grid and the
dropdowns disappeared.

The month is now clamped to the navigation range on every render, which
is what already happens when `month` is controlled.

Closes gpbl#2912
@nahuelsoria
nahuelsoria requested a review from gpbl as a code owner August 12, 2026 19:35
@changeset-bot

changeset-bot Bot commented Aug 12, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 5ef25b1

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 7 packages
Name Type
@daypicker/buddhist Patch
@daypicker/ethiopic Patch
@daypicker/hebrew Patch
@daypicker/hijri Patch
@daypicker/persian Patch
@daypicker/react Patch
react-day-picker Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Changing endMonth to a date smaller than the currently viewed month removes the month grid and dropdowns

1 participant