You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
fix(react-calendar-preview): preserve focus and grid keyboard ownership - #36884
Calendar focus restoration relied on styled picker class names, and base month/year grids had no two-dimensional arrow navigation. Native grid or focusgroup owners could move focus before consumer handlers had a chance to cancel; modified arrows in the day grid were also intercepted.
New Behavior
Use reserved picker data markers for class-independent focus restoration, and provide row/column arrow navigation for base month/year grids with RTL, boundary, unavailable-cell, and allFocusable handling. Navigation skips candidates that cannot receive focus while retaining programmatic focus for tabIndex="-1" cells.
Owned arrows dispatch consumer handlers before native grid owners while preserving nested focusgroup/grid ownership, editable targets, modified arrows, cancellation, and normal bubbling for other keys. Day-slot callbacks follow the target's ancestor path in capture/bubble order with correct currentTarget, exactly-once dispatch, and element-scoped deduplication that does not suppress callbacks in nested Calendars. preventDefault() cancels navigation without suppressing consumer bubbling; a cell bubbling callback can stop propagation without cancelling Calendar movement.
Native-owner cancellation ordering relies on React 17+ capture delegation. No special React 16 native event bridge is included; the package peer range is unchanged.
These stable Calendar fixes are required by #36752: its headless Calendar wrappers compose the same base primitives and need the correct focus-restoration and keyboard behavior. This PR contains the shared Calendar implementation, regression tests, specification updates, and one patch change file; #36752 adds the headless wrappers and their public API.
Use reserved day/month root markers to preserve focus restoration for base and headless compositions. Add styled/classless and SSR regressions, document the markers, and include a patch change file.
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: ed39bb7d-827b-40e9-bc3b-3bf27e334d85
Revert Calendar behavior fixes for a separate PR and remove the unrelated CI changes, restoring the original two-file release tree.
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: ed39bb7d-827b-40e9-bc3b-3bf27e334d85
Restore the existing Calendar-only focus and keyboard fixes from the saved source snapshot, preserving the source, tests, and specification exactly. Consolidate the related release notes into one scoped patch change.
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 92cc9ccd-6e8f-4638-8c08-b2323aa950a1
Restore private:true from master and remove the original initial-release change file from the Calendar source-only PR. Retain the consolidated patch note and the Calendar source, tests, and specification unchanged.
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 92cc9ccd-6e8f-4638-8c08-b2323aa950a1
Updates shared Calendar primitives to preserve class-independent focus restoration and keyboard ownership, supporting the headless Calendar wrappers in #36752.
Changes:
Adds picker markers for focus restoration.
Implements month/year grid arrow navigation and shared keyboard ownership handling.
Adds regression tests, specification updates, and a patch change file.
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the focus and keyboard-ownership improvements. I verified the focused-button cancellation fix; the 667 Calendar unit tests, 41 browser tests, lint, and type-check pass. I am requesting changes for the five remaining issues described in the code-targeted comments in this single batched review.
The reason will be displayed to describe this comment to others. Learn more.
I've taken another look at the latest changes.
The earlier examples are fixed.
This pass found two more issues that were already present, plus one regression introduced by the latest changes. I've left the three comments.
Calling the composed handler during cell capture moves focus before capture handlers on custom descendants run. For example, a focusable span supplied through dayLabel.children or renderYear cannot cancel ArrowRight with onKeyDownCapture={event => event.preventDefault()}. Forwarding the known day-slot roots does not cover these children; it also invokes slot bubbling callbacks before a child's stopPropagation() can suppress them. Adjust dispatch so custom descendant handlers run before navigation, while retaining native-grid cancellation ordering, and add nested-child cancellation and propagation tests.
This predicate captures arrows from non-editable renderYear descendants before their handlers run. If renderYear returns a focusable span whose onKeyDownCapture or onKeyDown calls preventDefault(), ArrowRight moves focus before that cancellation occurs. Restrict early dispatch to cell-targeted events and leave custom descendants in normal bubbling, as the day-cell predicate does. Add descendant cancellation tests for both phases.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Previous Behavior
Calendar focus restoration relied on styled picker class names, and base month/year grids had no two-dimensional arrow navigation. Native grid or focusgroup owners could move focus before consumer handlers had a chance to cancel; modified arrows in the day grid were also intercepted.
New Behavior
Use reserved picker data markers for class-independent focus restoration, and provide row/column arrow navigation for base month/year grids with RTL, boundary, unavailable-cell, and
allFocusablehandling. Navigation skips candidates that cannot receive focus while retaining programmatic focus fortabIndex="-1"cells.Owned arrows dispatch consumer handlers before native grid owners while preserving nested focusgroup/grid ownership, editable targets, modified arrows, cancellation, and normal bubbling for other keys. Day-slot callbacks follow the target's ancestor path in capture/bubble order with correct
currentTarget, exactly-once dispatch, and element-scoped deduplication that does not suppress callbacks in nested Calendars.preventDefault()cancels navigation without suppressing consumer bubbling; a cell bubbling callback can stop propagation without cancelling Calendar movement.Native-owner cancellation ordering relies on React 17+ capture delegation. No special React 16 native event bridge is included; the package peer range is unchanged.
These stable Calendar fixes are required by #36752: its headless Calendar wrappers compose the same base primitives and need the correct focus-restoration and keyboard behavior. This PR contains the shared Calendar implementation, regression tests, specification updates, and one patch change file; #36752 adds the headless wrappers and their public API.
Validation
NX_DAEMON=false yarn nx run react-calendar-preview:test --runInBand --verbose=false— passed (19 suites, 699 tests).NX_DAEMON=false yarn nx run react-calendar-preview:e2e --browser chrome --spec src/components/Calendar/Calendar.cy.tsx— passed (50 browser tests).NX_DAEMON=false yarn nx run-many --projects=react-calendar-preview --targets=lint,type-check --parallel=2— passed.git diff --check— passed.Related Issue(s)