MudDatePicker: Add keyboard navigation#12028
Conversation
d14ba74 to
88ec782
Compare
There was a problem hiding this comment.
Pull Request Overview
This PR enhances keyboard navigation in the MudDatePicker component by implementing arrow key navigation across different picker views (Date, Month, Year) and enabling Enter key selection. The changes also include focus management improvements and mouse event handling adjustments.
- Implemented arrow key navigation (left/right/up/down) for navigating dates, months, and years
- Enhanced Enter key handling to select the currently highlighted date/month/year based on the current view
- Added FocusAsync() calls when clicking on dates, months, and years for better accessibility
- Modified event handlers to prevent default mouse behavior on certain picker elements
Reviewed Changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated 3 comments.
| File | Description |
|---|---|
| MudDatePicker.cs | Core logic for keyboard navigation: arrow key handlers for navigating dates/months/years, Enter key selection for highlighted items, and FocusAsync calls in click handlers |
| MudBaseDatePicker.razor.cs | Changed visibility of helper methods/fields from private to protected, updated ScrollToYear to accept optional date parameter, trailing whitespace cleanup |
| MudBaseDatePicker.razor | Added mousedown preventDefault attributes to toolbar and calendar content, cleaned up lambda expressions |
| DatePickerTests.cs | Added comprehensive test for keyboard navigation and date selection workflow |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
88ec782 to
d696c07
Compare
danielchalmers
left a comment
There was a problem hiding this comment.
The code is fairly dense and nested with no comments. Could you also expand on the PR description with images/videos?
db8b8b0 to
966ebda
Compare
igotinfected
left a comment
There was a problem hiding this comment.
Very cool feature, thanks!
Added some minor code suggestions.
Here's a list of issues I came across while testing (none of them blocking for the PR I believe):
- keyboard navigation doesn't work on a
DatePickerwithPickerVariant="PickerVariant.Static" - in the fixed values usage section
- when the month is fixed you can get into a weird state by using the
Shift+Left/Right Arrowshortcuts
- when the month is fixed you can get into a weird state by using the
- when the year is fixed, when you click on the year while you're in the day view you can get into a weird state (click any day, then click on the year)
- because of the change to the
MudPicker.razor(KeyDownPreventDefault="Open") file, when any picker popup is open you can no longer type into the text field (probably not an issue but good to know)
We should also add a section to the DatePicker docs listing all the new shortcuts, you can refer to MudRating for an example.
| protected override RenderFragment PickerContent => | ||
| @<CascadingValue Value="@this" IsFixed="true"> | ||
| <MudPickerToolbar Class="mud-picker-datepicker-toolbar" ShowToolbar="@ShowToolbar" Orientation="@Orientation" PickerVariant="@PickerVariant" Color="@Color"> | ||
| <MudPickerToolbar Class="mud-picker-datepicker-toolbar" ShowToolbar="@ShowToolbar" Orientation="@Orientation" PickerVariant="@PickerVariant" Color="@Color" @onmousedown:preventDefault="true"> |
There was a problem hiding this comment.
out of curiosity -- why is the onmousedown needed?
There was a problem hiding this comment.
@igotinfected to not lose focus on input field, when clicking buttons in toolbar
| @@ -259,17 +276,67 @@ protected internal override async Task OnHandleKeyDownAsync(KeyboardEventArgs ar | |||
| case "ArrowRight": | |||
| if (Open) | |||
There was a problem hiding this comment.
you could invert the if to reduce nesting
| if (Open) | ||
| { | ||
|
|
||
| if (args.ShiftKey) |
There was a problem hiding this comment.
this if and the switch + case below could be a single if
| } | ||
|
|
||
| break; | ||
| case "ArrowLeft": |
There was a problem hiding this comment.
same comments as for ArrowRight case
| @@ -279,12 +346,52 @@ protected internal override async Task OnHandleKeyDownAsync(KeyboardEventArgs ar | |||
| } | |||
| else if (args.ShiftKey) | |||
There was a problem hiding this comment.
if/switch can be simplified
| @@ -293,35 +400,93 @@ protected internal override async Task OnHandleKeyDownAsync(KeyboardEventArgs ar | |||
| } | |||
| else if (args.ShiftKey) | |||
| /// Scrolls to the current year. | ||
| /// </summary> | ||
| public async void ScrollToYear() | ||
| public async Task ScrollToYear(DateTime? date = null) |
There was a problem hiding this comment.
add Async suffix to indicate it's an async method
966ebda to
8fa05bd
Compare
|
Thank you for this! |
Features:
When popup is opened it can be navigated with keys:
Arrows keys:
Navigates years/months/days in respective views
Shift + arrows keys:
Navigates years in month view
Navigates years and months in date view
Enter:
Selects value in current view and moves to next view or commits value to input and closes popup on last view
Backspace
Closes popup when first view and doesnt commit value to input
Moves to previous view if not first view
Fixes:
Datepicker now retains focus when value is selected
Recording.2025-11-10.130047.mp4