New component plan: FluentDateRangePicker
#5024
Vincent Baaij (vnbaaij)
started this conversation in
Ideas
Replies: 2 comments 5 replies
|
0 replies
|
I like this plan! I'm already thinking of places I could use this. There are perhaps a few options that could be nice to add:
|
5 replies
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Following the discussion in #5019, I propose we ad a new component to the library: the
FluentDateRangePickerBased on going back and forth with my assistant, we came up with the below plan. Please read ,suggest, comment, etc.
Create FluentDateRangePicker component
Understanding
Create
FluentDateRangePicker<TValue>— a dedicated date range picker that wrapsFluentCalendar<TValue>inCalendarSelectMode.Rangemode. It binds to two independentTValueparameters (StartandEnd), and usesFluentInputBase<(TValue, TValue)>internally to gain form integration, validation, and field properties (Label, Disabled, Required, etc.). The control must support both popup selection and accessible manual entry of a start/end range through a maskedFluentTextInput, while still auto-swapping Start/End if End < Start.Assumptions
FluentInputBase<(TValue, TValue)>(ValueTuple of two dates as the internal binding).@bind-Startand@bind-Endas independentTValueparameters that map to/from the tupleCurrentValue.SelectModeis hardcoded toCalendarSelectMode.Range— no user control.if (typeof(TValue).IsNotDateType()) throw.Culture,MinDate,MaxDate,DisabledDateFunc,DisabledCheckAllDaysOfMonthYear,DisabledSelectable,DayFormat,View.FluentInputBasemembers:Label,Disabled,ReadOnly,Required,Message*,AriaLabel,Autofocus,Name,FocusLost, etc.FormatValueAsString: "start – end" format or empty if both null.TryParseValueFromString: custom parsing for manually entered range text and validation errors for incomplete/invalid ranges.AutoCloseparameter support so consumers can control whether the popup closes automatically when a complete range is selected.AutoClosetotrueto preserve the planned close-on-complete behavior.End < Start, auto-swap them and triggerSelectedDatesChanged.SelectDatesHoverfor preset ranges (e.g., "this week", "this month").FluentTextInputmask support plus customized parsing/validation rather than a display-only input.FluentTextInputmask-related parameters throughFluentDateRangePickerso developers can configure them.MaskPatternis provided, auto-generate the pattern from the active culture/date format and configured separator so both start and end dates can be entered.MaskPattern, validate that it supports entry of both Start and End values in the combined range input..github/workflows/build-core-lib.ymlandtests/_StartCodeCoverage.ps1.Approach
FluentDateRangePicker.razor.cs
FluentDateRangePicker.razor
FluentTextInputwith calendar icon inEndTemplate.MaskPattern,MaskLazy, andMaskPlaceholderto the internalFluentTextInputso developers can configure masking behavior.MaskPatternis omitted, apply an auto-generated culture-aware range mask that supports both start and end date entry and uses the configured separator.FluentPopovercontainingFluentCalendarwithSelectMode="CalendarSelectMode.Range"hardcoded.SelectedDates(derived fromStart/End), with all 8 params forwarded.FluentDateRangePicker.razor.css
ComponentBaseTests.cs
FluentDateRangePicker<>entry withDateTimetype arg.InputBaseTests.cs
typeof(FluentDateRangePicker<>)toExcludedarray.FluentDateRangePickerTests.razor
AutoClose=trueandAutoClose=falsebehavior, andSelectDatesHoverpreset ranges.DateRangePickerExample.razor
AutoCloseusage, and preset ranges demo.FluentDateRangePicker.md
tests/_StartCodeCoverage.ps1
Key Files
src/Core/Components/DateTime/FluentDateRangePicker.razor.cs— code-behind (new)src/Core/Components/DateTime/FluentDateRangePicker.razor— markup (new)src/Core/Components/DateTime/FluentDateRangePicker.razor.css— styles (new)src/Core/Components/DateTime/FluentCalendarBase.cs— reference only, NOT modifiedsrc/Core/Components/DateTime/CalendarTValue.cs— reference forIsNotDateTypeguardtests/Core/Components/DateTimes/FluentDateRangePickerTests.razor— bUnit tests with coverage-driven scenarios (new)tests/Core/Components/Base/ComponentBaseTests.cs— add entry (modify)tests/Core/Components/Base/InputBaseTests.cs— add to Excluded (modify)tests/_StartCodeCoverage.ps1— local coverage validation at the repository 98% threshold.github/workflows/build-core-lib.yml— CI coverage threshold reference (MIN_COVERAGE: 98)examples/.../DatePicker/Examples/DateRangePickerExample.razor— demo (new)examples/.../DatePicker/FluentDateRangePicker.md— docs (new)Risks & Open Questions
FluentInputBase<(TValue, TValue)>— is there precedent in the codebase? Check if ValueTuple works cleanly with edit context validation.SelectedDatesChanged? Yes; it's a semantic correction.IEnumerable<TValue>getter that returnsnew[] { Start, End }for consumers who prefer that interface? Yes, add as a convenience property.AutoClose=falsechanges the post-selection interaction model; tests must verify the popup remains open after a complete range is selected.Steps
FluentDateRangePicker.razor.csFluentInputBase<(TValue, TValue)>IsNotDateTypeStart/Endparameters backed by tupleCurrentValueAutoClose,MaskPattern,MaskLazy,MaskPlaceholder, andRangeSeparatorFormatValueAsString,TryParseValueFromString, helper methods for parsing a typed start/end range, and effective mask generation/validation logicOnTextInputClickAsync,OnIconKeydownAsync,OnSelectedDatesChangedAsync(with auto-swap and conditional close behavior)SelectedDatesproperty returningnew[] { Start, End }ClassValue,StyleValue,GetPlaceholderhelpersFluentDateRangePicker.razorFluentTextInputwith iconEndTemplateMaskPatternor a culture-generated default mask for the combined start/end valueFluentPopover+FluentCalendarwithSelectMode="Range"hardcodedFluentDateRangePicker.razor.cssComponentBaseTests.csFluentDateRangePicker<>→DateTimeentryInputBaseTests.cstypeof(FluentDateRangePicker<>)toExcludedarrayFluentDateRangePickerTests.razorMaskLazy/MaskPlaceholder, and invalid custom mask rejectionAutoClose=trueclose-on-complete andAutoClose=falsestay-open behaviorSelectDatesHoverpresetsDateRangePickerExample.razorAutoClose, and preset ranges demoFluentDateRangePicker.mdAutoClosetests/_StartCodeCoverage.ps1(or equivalent coverage command) and confirm line coverage remains at or above 98%All reactions