Skip to content

fix: stop CalendarYearPicker from looping at year 9999 - #10841

Open
mangeshraut712 wants to merge 2 commits into
adobe:mainfrom
mangeshraut712:cursor/fix-calendar-year-picker-9999-0538
Open

mangeshraut712 wants to merge 2 commits into
adobe:mainfrom
mangeshraut712:cursor/fix-calendar-year-picker-9999-0538

Conversation

@mangeshraut712

Copy link
Copy Markdown

Closes #10839

useCalendarYearPicker walks years with date.add({years: 1}) and keeps going while the date is still inside the range, or still in the maximum year, so a minValue/maxValue pair that ends mid-year still includes that last year. Gregorian dates cannot move past 9999: new CalendarDate(9999, 12, 31).add({years: 1}) stays 9999-12-31. The condition never becomes false, the year list grows without bound, and rendering CalendarYearPicker focused on December 9999 locks the page. Clamping can also land a later day in 9999, which would list that year twice.

After a year is added, stop when the next step is still that same year. The final supported year is included once. When maxValue cuts that year short, the option date stays on maxValue, same as the fix for the mid-year range in #10531. With no explicit maximum, a focused date of 9999-12-01 shows 9989–9999 (the centered window cannot extend past the calendar maximum, and nothing shifts it). An explicit maxValue of 9999-06-01 still anchors a full 20-year list that ends on that date.

✅ Pull Request Checklist:

  • Included link to corresponding React Spectrum GitHub Issue.
  • Added/updated unit tests and storybook for this change (for new code or code which already has tests).
  • Filled out test instructions.
  • Updated documentation (if it already exists for this component).
  • Looked at the Accessibility Practices for this feature - Aria Practices
  • I understand every change in this PR and can explain why it's there.
  • If AI-assisted, I followed our AI contribution guidance and pointed my assistant at AGENTS.md.

No storybook or docs change: the public API and the year control are the same, and the list is just finite. Accessibility behavior of the picker is unchanged.

AI assistance: an assistant, pointed at AGENTS.md, reproduced the hang, added the regression test, and made this change.

📝 Test Instructions:

  1. Render a Calendar with defaultFocusedValue={new CalendarDate(9999, 12, 1)} and a CalendarYearPicker (the snippet in CalendarYearPicker enters an infinite loop at Gregorian year 9999 #10839).
  2. The picker should finish rendering. Years are 9989–9999, 9999 appears once and is selected, and its option date is 9999-12-01.
  3. Focused on 9999-12-31, the last option is 9999-12-31 and the list still ends.
  4. With maxValue={new CalendarDate(9999, 6, 1)} and focus in December 9999, the list is 9980–9999 and the last option is 9999-06-01.
  5. With minValue 9998-08-03, maxValue 9999-02-03, and focus in February 9999, the options are 9998 and 9999, and 9999 is backed by 9999-02-03.

Before the fix, the new test never returned and the Jest process ran out of memory. The loop is synchronous, so the test timeout does not interrupt it.

After the fix:

  • yarn test packages/react-aria-components/test/Calendar.test.js packages/react-aria-components/test/RangeCalendar.test.tsx — 63 passed
  • yarn lint — format check, yarn check-types, oxlint, package lint, and constraints passed

No separate mouse, keyboard, screen reader, RTL, or forced-colors pass: this only changes how many year options are built.

🧢 Your Project:

Personal contribution.

Please tell me if you would rather shift the default window so a full visibleYears list still ends on 9999.

Date arithmetic clamps at the calendar maximum, so stepping forward
from year 9999 repeats that year and never returns. Stop once the next
step stays in the year just added, and keep that year inside maxValue.
snowystinger
snowystinger previously approved these changes Oct 23, 2026

@snowystinger snowystinger left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the PR

A centered window shrinks at the minimum and maximum year. Slide the free end so visibleYears entries remain, and cover those boundaries in other calendars and locales.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

CalendarYearPicker enters an infinite loop at Gregorian year 9999

2 participants