Skip to content

fix(RangeCalendar): keep the anchor date when focus moves into a month or year picker popover - #10890

Open
costajohnt wants to merge 1 commit into
adobe:mainfrom
costajohnt:fix/range-calendar-picker-commit
Open

costajohnt wants to merge 1 commit into
adobe:mainfrom
costajohnt:fix/range-calendar-picker-commit

Conversation

@costajohnt

Copy link
Copy Markdown
Contributor

Closes #10881

After picking a start date in a RangeCalendar, opening a CalendarMonthPicker or CalendarYearPicker rendered as a Select committed the range as start = end. Inside a DateRangePicker that commit also closed the popover, so a range could not span months through the pickers.

The commit came from the onBlur handler in useRangeCalendar, which runs commitBehavior whenever focus leaves the calendar's DOM. The picker's popover is portaled, so two blurs looked like leaving the calendar:

  1. Focus moving from the picker's trigger (inside the calendar) into its popup.
  2. Focus moving between options inside the popover. React bubbles these blur events through the portal to the calendar, with both target and relatedTarget outside its DOM.

The handler now returns early for both: when the blur target is not inside the calendar (the same portal check useFocusWithin uses), and when the target is an expanded trigger (aria-expanded="true"). Tabbing away, clicking outside, and the pointerup path behave as before. When the popover closes, focus returns to the trigger inside the calendar, so leaving the calendar afterwards still commits.

One tradeoff: if an app puts a non-modal disclosure-style button inside the calendar and the user tabs out of the calendar while it is still expanded, the range is no longer committed on that blur (the anchor stays and the next click still completes the range). RAC's Select popover is modal, so this does not apply to the picker pattern in the docs.

✅ 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.

Added a test in RangeCalendar.test.tsx that picks a start date, chooses June from a Select-based CalendarMonthPicker, and picks the end date. It fails on main (onChange fires with Apr 8 to Apr 8 when the popover opens) and passes with this change. The calendar and date picker suites in react-aria, react-aria-components, @adobe/react-spectrum and S2 pass, apart from four CalendarDateTime time-field tests in the v3 DatePicker/DateRangePicker suites that fail the same way on main locally. Drafted with Claude Code; I reviewed the change and the tests myself.

📝 Test Instructions:

  1. Open the RangeCalendar story or docs example with month and year pickers (https://react-aria.adobe.com/RangeCalendar#month-and-year-pickers).
  2. Click a date to start a range.
  3. Open the month picker and choose another month.
  4. Click a date. The range should run from the first date to the second.
  5. Repeat inside a DateRangePicker with the same pickers: the popover should stay open after choosing the month and close once the end date is picked.
  6. Start a range and tab out of the calendar: the range still commits as before.

🧢 Your Project:

Personal

…h or year picker popover

Opening a CalendarMonthPicker or CalendarYearPicker popover moved focus out
of the calendar's DOM, so the blur handler committed the in-progress range
as start = end (and closed a DateRangePicker). Ignore blurs that bubble
through portals and focus moving from an expanded trigger into its popup.
@dannify
dannify requested a review from devongovett October 29, 2026 20:57
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.

RangeCalendar: opening the CalendarMonthPicker / CalendarYearPicker popover commits the in-progress range

1 participant