Repository navigation
fix(Calendar): a two-month calendar keeps max's month in the last pane - #11202
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
AI review status for this pull request.
|
PR Analysis Report🔎 Preview ·
|
| Component | Size | LoC | Visual · A11y · RTL |
|---|---|---|---|
| DateTimeInput | 215.4 kB (+109 B) · 18.7 kB CSS (0) | — | — · — · — |
| DateRangeInput | 97.5 kB (+107 B) · 12.5 kB CSS (0) | — | — · — · — |
| Calendar · Storybook | 74.4 kB (+102 B) · 10.6 kB CSS (0) | 1,798 (+45) | ✓ · ✓ · ✓ |
2 more components
| Component | Size | LoC | Visual · A11y · RTL |
|---|---|---|---|
| PowerSearch | 299.2 kB (+95 B) · 24.7 kB CSS (0) | — | — · — · — |
| DateInput | 192.7 kB (+93 B) · 17.0 kB CSS (0) | — | — · — · — |
Package size: @astryxdesign/core 7.36 MB packed (+868 B); no new dependencies.
Touched components checked; add ci:run-visual or ci:run-rtl to run the full suites.
Generated by PR Enrichment workflow | View full report
There was a problem hiding this comment.
This pull request is on hold for an engineering owner's decision, and no code change is needed for it.
The Calendar spec (component:Calendar) does not yet decide which month a two-month calendar opens on. This change picks a rule for two cases: today in max's month, and a selected value that starts in max's month. The second case also ends the current rule that the value's month always comes first. Approval needs an engineering owner to provide or confirm the governing spec for both cases. They record it by commenting /approve-spec <full head SHA> here, and the author can do so only if they are an engineering owner.
CI has not run yet. A maintainer adds the ci:run label so it runs.
| * The same shift applies when the value or today is inside the window but in | ||
| * `max`'s month (`max` set to today is the common case): the month stays in | ||
| * view, in the last pane, and the panes before it show months that still have | ||
| * selectable days. |
There was a problem hiding this comment.
Non-blocking: this is one 46-word sentence with three topics, and INV29 asks for at most 25 words per descriptive sentence, one topic each. Suggested:
* The same shift applies when the value or today is in `max`'s month.
* That month then shows in the last pane. The earlier panes show months
* with selectable days.| * Moves the opening month back when `date`'s month is shown but a later pane | ||
| * would lie wholly past `max`: the last pane lands on `max`'s month, and the | ||
| * first pane never goes before `min`'s month. A date whose panes already end | ||
| * by `max`'s month, or whose own month is past `max`'s, is returned unchanged, | ||
| * so its month always stays in view. |
There was a problem hiding this comment.
Non-blocking: these sentences run 35 and 26 words, and the second is passive. INV29 asks for at most 25 words, active voice. Suggested:
* Moves the first pane back so that no pane lies wholly past `max`. The last
* pane then shows `max`'s month. The first pane never goes before `min`'s
* month. A date in an earlier month, or past `max`'s month, comes back
* unchanged.| // `min` is closer than the full shift: go back only as far as its month, | ||
| // and not at all when the date's own month is already there or earlier. |
There was a problem hiding this comment.
Non-blocking: Calendar renders only one or two panes, and with two panes latestFirstPane is before minMonth only when min is in max's month, so month equals minMonth and this always returns date. The minDate branch and this 29-word instruction cover a layout that cannot occur. Consider returning date here, or shortening the comment to "min's month limits the shift."
|
/approve-spec 44bac6f |
There was a problem hiding this comment.
Approved pending CI: CI has not run on this head yet. A maintainer adds the ci:run label so CI runs; the label takes effect on the next push, or a close and reopen.
An engineering owner approved the new opening-month rule for both cases (today in max's month, and a selected value that starts in max's month), and the tests pin both shifts and every unchanged path.
Optional, non-blocking:
- The new comments in
getInitialFocusDate.tswould read better as one short sentence per fact; the inline suggestions on those lines still apply. - The
focusDatedocs inCalendar.tsxandCalendar.doc.mjsstill say an unsetfocusDateopens on the selected date or today; a note on the two-month rule would keep them accurate.
|
/approve-spec 2e0da24 |
There was a problem hiding this comment.
Approved. An engineering owner approved the new opening-month rule for this head, for both cases (today in max's month, and a selected value that starts in max's month), the tests pin both shifts and the unchanged paths, and CI passes.
Optional, non-blocking:
- The new comments in
getInitialFocusDate.tswould read better as one short sentence per fact; the earlier inline suggestions on those lines still apply. - The
focusDatedocs inCalendar.tsxandCalendar.doc.mjsstill say an unsetfocusDateopens on the selected date or today; a note on the two-month rule would keep them accurate. - Newly live check: the description lists "a value past
max" as unchanged, but a value pastmaxinsidemax's own month now opens one month earlier, as the value rule says; "a value in a month aftermax's" would be exact.
Claims and files checked
- Changeset: a two-month calendar whose
maxis in its opening month now shows that month in the second pane: verified (getInitialFocusDate.ts:91-99,:127-133; new unit cases). - Changeset: before, with
maxset to today or a value starting inmax's month, it opened on that month and a fully disabled next month: verified against the base logic. - Changeset: the first pane never goes before
min's month: verified (:172-178; "does not shift back past min"). - Changeset: an explicit
focusDateis shown as given: verified (:84-86). - Changeset: a one-month calendar is unchanged: verified (
:151). - Description:
DateRangeInputopens two months by default and passes nofocusDate: verified (DateRangeInput.tsx:588,:950-963). - Description: the base shifted only when today was after
maxand otherwise returned today or the value's start: verified (basegetInitialFocusDate.ts). - Description: the linked issue asks for the shift from today or the value, stopping at
min's month: verified (the quote paraphrases the issue's expected behavior). - Description: one helper serves the value path and the in-window today path: verified (
:92,:127). - Description:
focusDate, a value pastmax, a one-month calendar and the today-after-maxbranch are unchanged: verified for a value in a month aftermax's; see the note above. - Description: no API, visual-style or navigation change: verified (no export, style or navigation code changes; the API report lists no change).
- Description: 5 of the new unit cases fail without the fix: verified (5 of 11 fail against the base logic).
- Description: 26 unit cases pass, with 11 new unit cases and 2 new render cases: verified (CI passes all 26 unit cases and the Calendar suite on this head).
- Description: the max-is-today render case shows July–August 2026 with July 31 enabled: verified (the case passes in CI on this head).
- Description: the Calendar, DateRangeInput and DateInput suites and the repository checks pass: verified on this head by CI's test, typecheck and lint jobs (the suite totals differ after the merge from
main). - Files:
getInitialFocusDate.ts(non-blocking comment notes),getInitialFocusDate.test.ts(clear),Calendar.test.tsx(clear), the Changeset (clear).
Fixes #9357
User impact
Anyone using a two-month
Calendar, or aDateRangeInput(two months by default), withmaxin the month the calendar opens on. The common case ismaxset to today: the calendar opens on [this month, next month], every day of next month is disabled, and the previous month, which has selectable days, is hidden behind a Previous click. The same happens when the selected value starts inmax's month.Problem and solution fit
getInitialFocusDateshifted the panes back only when today was aftermax. When today, or the value's start, was on or beforemaxin the same month, it returned that date unchanged, so the second pane landed wholly pastmax. Half the calendar then shows nothing a user can pick, andDateRangeInputpasses nofocusDate, so an app cannot correct it. The fix applies the existing shift to these two cases as well.Expected behavior and authority
max's month, shift the panes back bynumberOfMonths - 1months, stopping atmin's month."getInitialFocusDatealready states the intent for the past-window case: opening on[max, max + 1]spends half the calendar on a month that is entirely out of bounds.Smallest restoration
One helper in
getInitialFocusDate.ts, used for the value and the in-window today paths. It moves the first pane back so the last pane ismax's month, never beforemin's month. Unchanged: an explicitfocusDate, a value pastmax, a one-month calendar, and the existing today-after-maxbranch. No API, visual, or navigation change.One point for review: the value path used to be left as given. A value that starts in
max's month now opens in the second pane; its month is still shown.Evidence
getInitialFocusDatecases fail (max is today, max later in the same month, min in the previous month, value in max's month, year boundary).getInitialFocusDate.test.ts26/26; a two-monthCalendarwithmax= today (21 Aug 2026) shows "July 2026 – August 2026" with July 31 enabled.maxin a later month still opens on today; the one-month layout still opens on today;focusDateinmax's month is honored as given.getInitialFocusDate.test.ts, 2 render cases inCalendar.test.tsx.Scope
Components: Calendar, DateRangeInput
Testing
pnpm vitest run packages/core/src/Calendar packages/core/src/DateRangeInput packages/core/src/DateInput— 33 files, 1095 tests pass.pnpm check:repo(pre-commit) passes.