Skip to content

Allow Shift+Tab out of CalendarDatePicker - #22370

Merged
MrJul merged 3 commits into
AvaloniaUI:mainfrom
NathanDrake2406:fix/15193-calendardatepicker-shift-tab
Oct 5, 2026
Merged

MrJul merged 3 commits into
AvaloniaUI:mainfrom
NathanDrake2406:fix/15193-calendardatepicker-shift-tab

Conversation

@NathanDrake2406

Copy link
Copy Markdown
Contributor

What does the pull request do?

Lets the keyboard leave a CalendarDatePicker backwards with Shift+Tab.

What is the current behavior?

CalendarDatePicker is focusable and a tab stop. When the picker receives focus, OnGotFocus moves focus to PART_TextBox.

With focus in the text box, Shift+Tab selects the picker as the previous tab stop. The picker then moves focus back to the text box. Focus never reaches the control before the picker.

What is the updated/expected behavior with this PR?

Scenario Before After
Shift+Tab from the text box Focus stays in the text box Focus moves to the previous control
Tab into the picker Text box gets focus, text is selected Same
Shift+Tab into the picker from the next control Text box gets focus Same
Tab from the text box Focus moves to the next control Same
picker.Focus() and pointer focus Picker is focusable Same

How was the solution implemented (if it's not obvious)?

The static constructor overrides IsTabStop to false for CalendarDatePicker. Tab navigation then treats the picker as a container and stops on the text box directly. AutoCompleteBox and NumericUpDown already do the same for the same reason: the control forwards focus to an inner text box.

Focusable stays true, and OnGotFocus is unchanged. In the Fluent and Simple templates, PART_Button is not focusable and PART_Calendar is inside the popup. The text box is therefore the only tab stop in the picker, as before.

The text selection on tab entry now comes from TextBox itself, which selects all text when it gets focus by tab.

Validation

  • Shift_Tab_From_TextBox_Should_Move_Focus_To_Previous_Control fails on the first commit and passes on the second commit.
  • Tab_Into_CalendarDatePicker_Should_Focus_TextBox_And_Select_Text and Shift_Tab_Into_CalendarDatePicker_Should_Focus_TextBox guard entry into the picker from both directions.
  • Ran the CalendarDatePickerTests class in Avalonia.Controls.UnitTests: 11 passed, 1 skipped (already skipped on main).
  • Ran a local headless window with the Simple theme and real Tab and Shift+Tab key presses across button, picker, button. Without the fix, the last Shift+Tab leaves focus in the text box. With the fix, the cycle works in both directions. This check is not part of the PR.

The test template now marks PART_Button as not focusable, to match both built-in themes.

Not in this PR

The issue also mentions inconsistent End key behavior after the text is selected. This PR does not change that behavior.

Checklist

Breaking changes

None in API. The default value of IsTabStop for CalendarDatePicker changes from true to false. A custom template without a focusable child no longer receives tab focus on the picker itself.

Fixed issues

Fixes #15193

Shift+Tab from the text box of a CalendarDatePicker does not reach the
previous control. The previous tab stop is the picker, and the picker
moves focus back to its text box, so focus stays in the text box.

The test fails until the picker leaves the tab order.
CalendarDatePicker is a tab stop, and it moves focus to its text box
when it receives focus. Shift+Tab from the text box selects the picker
as the previous tab stop, so focus returns to the text box and the
keyboard cannot leave the picker backwards.

Remove the picker from the tab order, as AutoCompleteBox and
NumericUpDown do. Tab navigation then reaches the text box directly in
both directions. The picker stays focusable, so pointer focus and
Focus() calls behave as before.

Fixes AvaloniaUI#15193
@NathanDrake2406
NathanDrake2406 marked this pull request as ready for review October 2, 2026 02:06
@github-actions

github-actions Bot commented Oct 2, 2026

Copy link
Copy Markdown

NuGet packages

The packages for this pull request have been published (workflow run):

@MrJul MrJul added bug backport-candidate-12.1.x Consider this PR for backporting to 12.1 branch area-controls labels Oct 2, 2026

@maxkatz6 maxkatz6 left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consistent with NumericUpDown and AutoCompleteBox

@MrJul
MrJul added this pull request to the merge queue Oct 5, 2026
Merged via the queue into AvaloniaUI:main with commit daed7a2 Oct 5, 2026
12 checks passed
grokys pushed a commit to Evan260/Avalonia that referenced this pull request Oct 7, 2026
* test(datepicker): cover Shift+Tab out of CalendarDatePicker

Shift+Tab from the text box of a CalendarDatePicker does not reach the
previous control. The previous tab stop is the picker, and the picker
moves focus back to its text box, so focus stays in the text box.

The test fails until the picker leaves the tab order.

* fix(datepicker): allow Shift+Tab out of CalendarDatePicker

CalendarDatePicker is a tab stop, and it moves focus to its text box
when it receives focus. Shift+Tab from the text box selects the picker
as the previous tab stop, so focus returns to the text box and the
keyboard cannot leave the picker backwards.

Remove the picker from the tab order, as AutoCompleteBox and
NumericUpDown do. Tab navigation then reaches the text box directly in
both directions. The picker stays focusable, so pointer focus and
Focus() calls behave as before.

Fixes AvaloniaUI#15193

* chore: trim code comments
MrJul pushed a commit that referenced this pull request Oct 9, 2026
* test(datepicker): cover Shift+Tab out of CalendarDatePicker

Shift+Tab from the text box of a CalendarDatePicker does not reach the
previous control. The previous tab stop is the picker, and the picker
moves focus back to its text box, so focus stays in the text box.

The test fails until the picker leaves the tab order.

* fix(datepicker): allow Shift+Tab out of CalendarDatePicker

CalendarDatePicker is a tab stop, and it moves focus to its text box
when it receives focus. Shift+Tab from the text box selects the picker
as the previous tab stop, so focus returns to the text box and the
keyboard cannot leave the picker backwards.

Remove the picker from the tab order, as AutoCompleteBox and
NumericUpDown do. Tab navigation then reaches the text box directly in
both directions. The picker stays focusable, so pointer focus and
Focus() calls behave as before.

Fixes #15193

* chore: trim code comments
@MrJul MrJul added backported-12.1.x and removed backport-candidate-12.1.x Consider this PR for backporting to 12.1 branch labels Oct 9, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Not possible to Shift+Tab out of CalendarDatePicker

3 participants