feat(react-headless-components-preview): add headless Calendar - #36752
Dmytro Kirpa (dmytrokirpa) wants to merge 1 commit into
Conversation
f0fd3df to
942f3e3
Compare
2958ce2 to
12b9e40
Compare
12b9e40 to
e60a935
Compare
e60a935 to
944ba48
Compare
| dayPicker: slot.always(props.dayPicker, { | ||
| defaultProps: { ...state.dayPicker, ref: state.dayPickerRef }, | ||
| elementType: CalendarDay, | ||
| }), |
There was a problem hiding this comment.
Could we merge the consumer’s picker ref with the internal ref here?
Supplying dayPicker={{ ref: consumerRef }} currently overrides the internal ref in defaultProps, which the Calendar needs for focus restoration after keyboard navigation.
The styled implementation already merges these refs—could we use the same approach for the day, month, and nested year pickers?
| dayPicker: NonNullable<Slot<typeof CalendarDay>>; | ||
|
|
||
| /** | ||
| * The month picker. Only rendered while `isMonthPickerVisible` is set. | ||
| */ | ||
| monthPicker: NonNullable<Slot<typeof CalendarMonth>>; | ||
| }; | ||
|
|
||
| export type CalendarProps = CalendarBaseProps & | ||
| ComponentProps<Partial<Pick<CalendarSlots, 'dayPicker' | 'monthPicker'>>>; |
There was a problem hiding this comment.
Could we preserve null in these picker-slot types?
The underlying Calendar supports dayPicker={null} for month-only selection and monthPicker={null} for a day-only calendar.
NonNullable currently prevents TypeScript consumers from using those configurations.
Would keeping that contract in the headless types make sense?
|
Pull request demo site: URL |
944ba48 to
592e1a5
Compare
| * @param ref - reference to the root element of Calendar | ||
| */ | ||
| export const useCalendar = (props: CalendarProps, ref: React.Ref<HTMLDivElement>): CalendarState => { | ||
| const state = useCalendarBase_unstable(props, ref); |
There was a problem hiding this comment.
Screen.Recording.2026-09-17.at.13.51.11.mov
Could we make the inherited focus tracking work without the styled picker classes?
I reproduced this in the PR’s headless Calendar preview: at 1000px wide, focus March in the month picker without activating it, then resize to 400px. The month picker unmounts and document.activeElement becomes BODY, rather than a cell in the remaining day grid.
The base hook tracks picker focus through .fui-CalendarDay and .fui-CalendarMonth, which the headless wrappers omit. As a diagnostic control, temporarily adding the month-picker class before focusing March made the same resize correctly restore focus to the selected day.
Could we use class-independent focus tracking and add a regression test for this transition?
There was a problem hiding this comment.
we should've switched to data attributes in on of the previous iterations, let me double check.
Summary
Adds the headless Calendar wrappers and exports for the stable Calendar primitives, with component tests, API report, bundle fixture, and Storybook documentation.
Stack
Depends on #36751, which promotes the underlying Calendar package.
Validation
yarn nx test react-calendar-preview --runInBandSupersedes
Replaces closed #36630 after the Calendar implementation was split into focused review layers.