feat(date-field): QuickBooks-style keyboard shortcuts#364
Conversation
Whole-date navigation from a focused date segment and while the calendar popover is open (all case-insensitive): - t today; m/h month start/end; y/r year start/end; w/k week start/end - '-' / '=' / '+' step a day, rolling month and year boundaries over - '/' advances to the next segment; Alt+down opens the calendar - a 2-digit year expands to the 2000s on blur Shortcut targets clamp to minValue/maxValue; in the open calendar they move the highlight like the arrows (Enter confirms). The shared command resolver lives in lib/date-shortcuts.ts so the field and calendar engines stay decoupled. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The main-merge combined the test's @internationalized/date import onto one line; oxfmt wants it split. Fixes the failing fmt:check CI step. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Previously "26" → 2026 only ran on whole-group blur, but the calendar icon lives inside the group — so tabbing year→icon left "26" showing until focus escaped the field entirely. Fire the expansion when the year segment itself loses focus (to a sibling, the icon, or outside). Idempotent, so the commitOnBlur backstop (which also feeds the leap-year day-clamp) still runs. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
| } else { | ||
| base = completeCalendarDate(fields) ?? ref; | ||
| } | ||
| let next = resolveDateShortcut(cmd, base, ref, locale); |
There was a problem hiding this comment.
This never accepts a firstDayOfWeek option — so DatePicker passes firstDayOfWeek to useCalendarState (date-field.tsx:276) but not to useDateFieldState (date-field.tsx:248–263). resolveDateShortcut then falls through to startOfWeek(base, locale, undefined), i.e. the locale default.
i.e There's a <DatePicker locale="en-US" firstDayOfWeek="mon" />. Focus a segment and press w → field jumps to Sunday (en-US locale default). Open the calendar and press w → highlight jumps to Monday (use-calendar-state.ts:280, which does forward firstDayOfWeek).
DatePicker forwarded firstDayOfWeek to useCalendarState but not to useDateFieldState, so `w`/`k` from a focused segment fell through to resolveDateShortcut's locale default while the open-calendar path used the prop — e.g. <DatePicker locale="en-US" firstDayOfWeek="mon" /> jumped the field to Sunday but the calendar to Monday. Thread firstDayOfWeek into useDateFieldState and pass it through to the resolver. Centralize the FirstDayOfWeek type in lib/date-shortcuts.ts (the resolver that consumes it) and re-export from use-calendar-state so existing import sites are unchanged. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
Good catch — fixed in 1fd47f3. Also moved the |
|
/review |
|
✅ API Design Review completed successfully! API Design Review complete for PR #364. The prior High issue (firstDayOfWeek not forwarded to useDateFieldState in DatePicker) is resolved per commit 1fd47f3. Impact analysis confirms no breaking API changes and no consumer regressions. One Low suggestion posted inline (DateField missing firstDayOfWeek prop for w/k shortcuts). Verdict: Approve. |
There was a problem hiding this comment.
Generated by API Design Review for issue #364 · 123.1 AIC · ⌖ 6.95 AIC · ⊞ 5.8K
Comment /review to run again
| // Let the keyboard shortcuts clamp into range (the field has no calendar to | ||
| // enforce it otherwise). | ||
| minValue, | ||
| maxValue, |
There was a problem hiding this comment.
[1/1 — Low] DateField has w/k shortcuts but no firstDayOfWeek prop
DatePicker now correctly forwards firstDayOfWeek to both useDateFieldState and useCalendarState so the field and calendar agree (that was the fix in 1fd47f3). However DateField (no calendar) also gets the new w/k shortcuts but its public DateFieldProps doesn't include firstDayOfWeek — so the week-start in a standalone DateField is locked to the locale default.
The risk is lower than the field/calendar disagreement that was fixed (there's no paired calendar to conflict with), but a consumer embedding DateField in a non-default-week-start locale has no way to override it.
Suggested fix (optional, non-blocking): move firstDayOfWeek?: FirstDayOfWeek into DateBehaviorProps (or add it directly to DateFieldProps) and thread it through the useDateFieldState call the same way DatePicker now does.
Verdict: Approve
The previously raised High issue has been addressed. Only this Low-severity suggestion remains — it does not block merging.
What
Adds QuickBooks Online-style keyboard shortcuts to
DateField/DatePicker. Fast-follow #1372 on the date-picker foundation (planning issue), which landed onmainvia #332.Shortcuts
From a focused date segment and while the calendar popover is open (all case-insensitive):
tm/hy/rw/k-=/+next day — both roll month and year boundaries over (+needs no Shift)/1means January, not the start of1x)Alt+↓DatePicker)A 1–2 digit year expands to the 2000s on blur (
26→2026).Video demo
date-keyboard-shortcuts.mp4
Invalid-date handling
minValue/maxValue— shortcut targets are clamped into range (field path and calendar path both), so a shortcut can never land out of bounds.isDateUnavailable— in the field it behaves like typing (free entry; the consumer validates); in the open calendar an unavailable day can be highlighted but not confirmed.Enter/click confirms.Structure
The shortcut vocabulary (
DateShortcut,DATE_SHORTCUT_KEYS,resolveDateShortcut) lives in a pure, React-freelib/date-shortcuts.tsthat both the field and calendar engines import — no cross-component coupling, and the date math is unit-tested directly.Testing
pnpm test— 1321 pass (incl. pure-resolver tests + field/calendar shortcut + clamp + popover-open coverage)/date-pickerdemo: today, month-start, min-clamp, and the popover-open highlight + Enter-to-confirm flow🤖 Generated with Claude Code