Rask
Rask
v0.23.1-alpha.0.526

Components

Datetime picker

A date and a time picked together from one field, for scheduling events, publishing posts, setting reminders or booking a window of time. For a date alone or a time alone, the date picker and the time picker serve better.

Drawn and behaving as Flux UI's datetime picker does, measured against its live docs.

Datetime picker

A day from the calendar and a time from the list beside it: the time closes it, a day alone changes the value at once.

DatetimePickerExample.cs
using System.Globalization;

namespace Rask.Site.Features.UiDocs.Examples;

public sealed partial class DatetimePickerExample : Component
{
    private DateTime _at = TimeProvider.System.GetLocalNow().Date.AddDays(5).AddHours(10).AddMinutes(30);

    protected override Component? Render() =>
        Div.Class("max-w-xs space-y-3")[
            Ui.DatetimePicker.Value(_at).OnChange(at => { _at = at; }),
            Ui.Text.Data("testid", "ui-datetime-picker-state")[_at == default ? "Nothing chosen." : "Chosen: " + _at.ToString("yyyy-MM-dd'T'HH:mm", CultureInfo.InvariantCulture)]
        ];
}
Live result
October 2026
Su
Mo
Tu
We
Th
Fr
Sa
Time

Chosen: 2026-10-31T10:30

Basic usage

Bound to a DateTime?: a wall-clock time, as a datetime-local field holds it.

DatetimePickerBoundExample.cs
using System.Globalization;

namespace Rask.Site.Features.UiDocs.Examples;

public sealed partial class DatetimePickerBoundExample : Component
{
    private readonly Event _event = new();

    protected override Component? Render() =>
        Div.Class("max-w-xs space-y-3")[
            Ui.DatetimePicker.Bind(() => _event.StartsAt).Live().Label("Starts at"),
            Ui.Text[_event.StartsAt is { } at ? "Starts " + at.ToString("yyyy-MM-dd'T'HH:mm", CultureInfo.InvariantCulture) + "." : "Not scheduled."]
        ];

    public sealed class Event
    {
        public DateTime? StartsAt { get; set; }
    }
}
Live result
October 2026
Su
Mo
Tu
We
Th
Fr
Sa
Time

Not scheduled.

Range picker

A UiDateTimeRange: each end gets its own time, and Select range applies it.

DatetimePickerRangeExample.cs
using System.Globalization;

namespace Rask.Site.Features.UiDocs.Examples;

public sealed partial class DatetimePickerRangeExample : Component
{
    private UiDateTimeRange _schedule;

    protected override Component? Render() =>
        Div.Class("max-w-xs space-y-3")[
            Ui.DatetimePicker.Range.Value(_schedule).OnChange(range => { _schedule = range; }),
            Ui.Text.Data("testid", "ui-datetime-picker-range-state")[_schedule == default ? "No window chosen." : "From " + At(_schedule.Start) + " to " + At(_schedule.End)]
        ];

    private static string At(DateTime at) => at.ToString("yyyy-MM-dd'T'HH:mm", CultureInfo.InvariantCulture);
}
Live result
October 2026
Su
Mo
Tu
We
Th
Fr
Sa
November 2026
Su
Mo
Tu
We
Th
Fr
Sa
Start
End

No window chosen.

Range limits

At most seven days, the start and the end days included.

DatetimePickerRangeLimitsExample.cs
namespace Rask.Site.Features.UiDocs.Examples;

public sealed partial class DatetimePickerRangeLimitsExample : Component
{
    protected override Component? Render() =>
        Div.Class("max-w-xs")[Ui.DatetimePicker.Range.Value(default(UiDateTimeRange)).MaxRange(7)];
}
Live result
October 2026
Su
Mo
Tu
We
Th
Fr
Sa
November 2026
Su
Mo
Tu
We
Th
Fr
Sa
Start
End

Time input

An exact time typed in parts, with the list as suggestions; for a moment and for a range.

DatetimePickerInputExample.cs
namespace Rask.Site.Features.UiDocs.Examples;

public sealed partial class DatetimePickerInputExample : Component
{
    protected override Component? Render() =>
        Div.Class("max-w-xs space-y-4")[
            Ui.DatetimePicker.Value(default(DateTime)).Time(Ui.DatetimePickerTime.Input),
            Ui.DatetimePicker.Range.Value(default(UiDateTimeRange)).Time(Ui.DatetimePickerTime.Input)
        ];
}
Live result
October 2026
Su
Mo
Tu
We
Th
Fr
Sa
Time
: 
October 2026
Su
Mo
Tu
We
Th
Fr
Sa
November 2026
Su
Mo
Tu
We
Th
Fr
Sa
Start
: 
End
: 

Interval

A time every 15 minutes; 30 when unset.

DatetimePickerIntervalExample.cs
namespace Rask.Site.Features.UiDocs.Examples;

public sealed partial class DatetimePickerIntervalExample : Component
{
    protected override Component? Render() =>
        Div.Class("max-w-xs")[Ui.DatetimePicker.Value(default(DateTime)).Interval(15)];
}
Live result
October 2026
Su
Mo
Tu
We
Th
Fr
Sa
Time

Default time

Filled in as soon as a day is picked; for a range, the start's and the end's.

DatetimePickerDefaultTimeExample.cs
namespace Rask.Site.Features.UiDocs.Examples;

public sealed partial class DatetimePickerDefaultTimeExample : Component
{
    protected override Component? Render() =>
        Div.Class("max-w-xs space-y-4")[
            Ui.DatetimePicker.Value(default(DateTime)).DefaultTime(new TimeOnly(9, 0)),
            Ui.DatetimePicker.Range.Value(default(UiDateTimeRange)).DefaultTime(new UiTimeRange(new TimeOnly(9, 0), new TimeOnly(17, 0)))
        ];
}
Live result
October 2026
Su
Mo
Tu
We
Th
Fr
Sa
Time
October 2026
Su
Mo
Tu
We
Th
Fr
Sa
November 2026
Su
Mo
Tu
We
Th
Fr
Sa
Start
End

Min/max

From now to two weeks on at 5 PM: the days outside are off, and on the first and last day so are the times outside.

DatetimePickerMinMaxExample.cs
namespace Rask.Site.Features.UiDocs.Examples;

public sealed partial class DatetimePickerMinMaxExample : Component
{
    private readonly DateTime _now = TimeProvider.System.GetLocalNow().DateTime;

    protected override Component? Render() =>
        Div.Class("max-w-xs")[Ui.DatetimePicker.Value(default(DateTime)).Min(_now).Max(_now.Date.AddDays(14).AddHours(17))];
}
Live result
October 2026
Su
Mo
Tu
We
Th
Fr
Sa
Time

Min/max times

Any future time between 9 AM and 5 PM: the times outside the window are not listed at all.

DatetimePickerMinMaxTimesExample.cs
namespace Rask.Site.Features.UiDocs.Examples;

public sealed partial class DatetimePickerMinMaxTimesExample : Component
{
    protected override Component? Render() =>
        Div.Class("max-w-xs")[
            Ui.DatetimePicker.Value(default(DateTime)).Min(TimeProvider.System.GetLocalNow().DateTime).MinTime(new TimeOnly(9, 0)).MaxTime(new TimeOnly(17, 0))
        ];
}
Live result
October 2026
Su
Mo
Tu
We
Th
Fr
Sa
Time

Unavailable dates and times

A whole day, a stretch of every day, and times of one day only. A stretch includes both its ends.

DatetimePickerUnavailableExample.cs
namespace Rask.Site.Features.UiDocs.Examples;

public sealed partial class DatetimePickerUnavailableExample : Component
{
    private readonly DateOnly _today = DateOnly.FromDateTime(TimeProvider.System.GetLocalNow().Date);

    protected override Component? Render() =>
        Div.Class("max-w-xs")[
            Ui.DatetimePicker.Value(default(DateTime)).Min(_today.ToDateTime(TimeOnly.MinValue)).MinTime(new TimeOnly(8, 0)).MaxTime(new TimeOnly(18, 0)).Unavailable([
                _today.AddDays(2),
                new UiTimeRange(new TimeOnly(12, 0), new TimeOnly(13, 0)),
                _today.AddDays(1).ToDateTime(new TimeOnly(10, 0)),
                UiDatetimeSlot.On(_today.AddDays(1), new TimeOnly(15, 0), new TimeOnly(16, 0)),
            ])
        ];
}
Live result
October 2026
Su
Mo
Tu
We
Th
Fr
Sa
Time

Time format

DatetimePickerFormatExample.cs
namespace Rask.Site.Features.UiDocs.Examples;

public sealed partial class DatetimePickerFormatExample : Component
{
    protected override Component? Render() =>
        Div.Class("flex flex-wrap gap-4")[
            Ui.DatetimePicker.Value(default(DateTime)).Label("12-hour").TimeFormat(Ui.DatetimePickerTimeFormat.TwelveHour),
            Ui.DatetimePicker.Value(default(DateTime)).Label("24-hour").TimeFormat(Ui.DatetimePickerTimeFormat.TwentyFourHour)
        ];
}
Live result
October 2026
Su
Mo
Tu
We
Th
Fr
Sa
Time
October 2026
Su
Mo
Tu
We
Th
Fr
Sa
Time

Clearable

DatetimePickerClearableExample.cs
namespace Rask.Site.Features.UiDocs.Examples;

public sealed partial class DatetimePickerClearableExample : Component
{
    private DateTime? _at = TimeProvider.System.GetLocalNow().Date.AddDays(3).AddHours(9);

    protected override Component? Render() =>
        Div.Class("max-w-xs space-y-3")[
            Ui.DatetimePicker.Value(_at ?? default).OnChange(at => { _at = at == default ? null : at; }).Clearable(),
            Ui.Text.Data("testid", "ui-datetime-picker-clear-state")[_at is null ? "Nothing chosen." : "A moment is chosen."]
        ];
}
Live result
October 2026
Su
Mo
Tu
We
Th
Fr
Sa
Time

A moment is chosen.

With confirmation

Nothing is written until Select; Cancel, Escape and a press outside drop the choice.

DatetimePickerConfirmationExample.cs
namespace Rask.Site.Features.UiDocs.Examples;

public sealed partial class DatetimePickerConfirmationExample : Component
{
    protected override Component? Render() =>
        Div.Class("max-w-xs")[Ui.DatetimePicker.Value(default(DateTime)).WithConfirmation()];
}
Live result
October 2026
Su
Mo
Tu
We
Th
Fr
Sa
Time

Custom trigger

DatetimePickerTriggerExample.cs
namespace Rask.Site.Features.UiDocs.Examples;

public sealed partial class DatetimePickerTriggerExample : Component
{
    protected override Component? Render() =>
        Div.Class("max-w-xs")[
            Ui.DatetimePicker.Value(default(DateTime)).Trigger(Ui.Button.Icon(Ui.IconName.CalendarDays)["Schedule"])
        ];
}
Live result
October 2026
Su
Mo
Tu
We
Th
Fr
Sa
Time

Calendar options

The date picker's own: the today shortcut, a selectable header, week numbers, the start day and fixed weeks.

DatetimePickerCalendarExample.cs
namespace Rask.Site.Features.UiDocs.Examples;

public sealed partial class DatetimePickerCalendarExample : Component
{
    protected override Component? Render() =>
        Div.Class("max-w-xs")[Ui.DatetimePicker.Value(default(DateTime)).WithToday().SelectableHeader().WeekNumbers()];
}
Live result
October 2026
#
Su
Mo
Tu
We
Th
Fr
Sa
40
41
42
43
44
Time

Open to

A moment to open on while nothing is chosen, or only a time: this month, the list scrolled to it.

DatetimePickerOpenToExample.cs
namespace Rask.Site.Features.UiDocs.Examples;

public sealed partial class DatetimePickerOpenToExample : Component
{
    protected override Component? Render() =>
        Div.Class("max-w-xs space-y-4")[
            Ui.DatetimePicker.Value(default(DateTime)).OpenTo(new DateTime(2026, 12, 1, 9, 0, 0, DateTimeKind.Unspecified)),
            Ui.DatetimePicker.Value(default(DateTime)).OpenTo(new TimeOnly(9, 0))
        ];
}
Live result
December 2026
Su
Mo
Tu
We
Th
Fr
Sa
Time
October 2026
Su
Mo
Tu
We
Th
Fr
Sa
Time

Localization

DatetimePickerLocaleExample.cs
namespace Rask.Site.Features.UiDocs.Examples;

public sealed partial class DatetimePickerLocaleExample : Component
{
    protected override Component? Render() =>
        Div.Class("max-w-xs")[Ui.DatetimePicker.Value(default(DateTime)).Locale("fr-FR")];
}
Live result
octobre 2026
lu
ma
me
je
ve
sa
di
Time

Separate date and time

A date picker and a time picker side by side, for a date and a time kept apart.

DatetimePickerSeparateExample.cs
namespace Rask.Site.Features.UiDocs.Examples;

public sealed partial class DatetimePickerSeparateExample : Component
{
    private readonly Meeting _meeting = new();

    public sealed class Meeting
    {
        public DateOnly? Day { get; set; }

        public TimeOnly? At { get; set; }
    }

    protected override Component? Render() =>
        Div.Class("flex max-sm:flex-col gap-2 w-full max-w-64 sm:max-w-96")[
            Ui.DatePicker.Bind(() => _meeting.Day).Class("flex-1"),
            Ui.TimePicker.Bind(() => _meeting.At).Class("sm:w-40")
        ];
}
Live result
October 2026
Su
Mo
Tu
We
Th
Fr
Sa

Behaviour

What it binds

Ui.DatetimePicker binds a DateTime or a DateTime?, Ui.DatetimePicker.Range a UiDateTimeRange — Flux's DateTimeRange: a Start and an End, HasStart and HasEnd, written in an address as 2026-10-14T22:00..2026-10-15T02:00. Precise to the minute: seconds are dropped. A bound value is written with the reader's next action, at once with .Live().

Unavailable takes UiDatetimeSlots, which a day (DateOnly), a stretch of every day (TimeOnly, UiTimeRange) and a time of one day (DateTime, UiDatetimeSlot.On(day, from, to)) each convert to, as Flux mixes them in one list. OpenTo takes a moment, a day or only a time.

When it writes

Picking a time closes the picker and writes the moment; changing only the day writes it at once and leaves the popup open. A day alone or a time alone is held until the other is there, and DefaultTime fills the time in as soon as a day is picked. A range, typed times and WithConfirmation() wait for Select instead; Cancel, Escape and a press outside drop what was held. A range whose end is not after its start says so and cannot be selected.

All of it is the browser's, as Flux's script keeps it: paging, the arrows, the times a day rules out, what the button says. The page hears the value, and nothing else.

Time zones

Wall-clock times, as a datetime-local field holds them: 2026-10-14T10:30 is half past ten that day and is not converted between zones. For readers in other zones, convert to and from theirs yourself — TimeZoneInfo.ConvertTimeToUtc(startsAt, reader) on the way in. Min and Max are moments of the server's clock: Flux's min="now" is .Min(DateTime.Now) of the clock you trust.

On a phone

Under 640 px it is the date picker's sheet: one month, the time a field under it with its own list, and Cancel and Select at its foot. Nothing is written until Select.

The keyboard

The calendar's keys are the date picker's. Tab goes from the month steps to the day, then to the time the column opens on.

Key
What happens
ArrowDown, ArrowUpIn the column of times: the next or the previous time that can be picked, stopping at the ends.
Home, EndIn the column of times: the first or the last.
Enter, SpacePicks the time in focus.
EscapeCloses, and drops what was held.

Reference

Ui.DatetimePicker

flux:datetime-picker

A field-shaped button over a calendar and a list of times in a popup. Ui.DatetimePicker picks a moment, Ui.DatetimePicker.Range a start and an end.

Step
Takes
What it does
.Bind(…)() => a DateTime, or a UiDateTimeRangeThe member it reads and writes: () => m.StartsAt, or a UiDateTimeRange. Or Value with OnChange.
.Value(…)a DateTime, or a UiDateTimeRangeWhat it holds, for a page that holds it itself.
.OnChange(…)a handler given the new valueRuns with the new value when it is chosen.
.AfterBind(…)a handler given the new valueRuns after Bind has written the model.
.Validate(…)a validatorA rule the value is checked by when it is written.
.Live()boolWrites the model as soon as it is chosen, not with the next action.
.Mode(…)
Ui.DatetimePickerMode
Single
Range

Each is a step of its own too, unless an HTML tag has its name.

What is picked, as a value. The opening step says it; this has to agree with what is bound.
.Time(…)
Ui.DatetimePickerTime
List
Input

Each is a step of its own too, unless an HTML tag has its name.

How times are chosen: from a list, or typed (Ui.DatetimePickerTime.Input). The list when unset.
.Interval(…)intMinutes between the times in the list. 30 when unset.
.TimeFormat(…)
Ui.DatetimePickerTimeFormat
Auto
TwelveHour
TwentyFourHour

Each is a step of its own too, unless an HTML tag has its name.

12-hour or 24-hour. The locale's own when unset.
.Min(…)a DateTimeThe earliest moment that can be picked: earlier days are off, and so are the earlier times of its day.
.Max(…)a DateTimeThe latest moment that can be picked.
.MinTime(…)a TimeOnlyThe earliest time of day listed, on every day.
.MaxTime(…)a TimeOnlyThe latest time of day listed, on every day.
.Unavailable(…)UiDatetimeSlot values: [day, new UiTimeRange(from, to), moment]Days, stretches of every day, and times of one day that cannot be picked.
.DefaultTime(…)a TimeOnly, or a UiTimeRangeThe time filled in as soon as a day is picked; for a range, the start's and the end's.
.MinRange(…)intThe fewest days a range may span, its ends included.
.MaxRange(…)intThe most days a range may span, its ends included.
.OpenTo(…)a DateTime, a DateOnly or a TimeOnlyWhere it opens while nothing is chosen: a moment, a day, or a time of today.
.Months(…)intHow many months are shown side by side. One, or two for a range, when unset.
.Size(…)
Ui.DatetimePickerSize
Default
Xs
Sm
Lg
Xl
Xxl

Each is a step of its own too, unless an HTML tag has its name.

How large the trigger and the calendar's day cells are.
.StartDay(…)
DayOfWeek
Sunday
Monday
Tuesday
Wednesday
Thursday
Friday
Saturday

Each is a step of its own too, unless an HTML tag has its name.

The day the week starts on. The locale's own when unset.
.WeekNumbers()boolShows each week's number.
.SelectableHeader()boolMakes the month and the year in the header selects.
.WithToday()boolA button that comes back to this month, and picks today once there.
.FixedWeeks()boolAlways six weeks, so paging never changes the height.
.WithConfirmation()boolHolds the choice until the reader presses Select. Always so for a range and typed times.
.Clearable()boolA button in the trigger that empties the picker, while something is chosen.
.Trigger(…)ComponentA trigger of your own: a Ui.Button, or a Ui.DatetimePickerButton.
.Label(…)stringDraws a field around it, with this label and the error.
.Description(…)stringHelp text between the label and the picker.
.DescriptionTrailing(…)stringHelp text under the picker.
.Badge(…)stringA word beside the label: "Optional".
.Placeholder(…)stringWhat the button shows while nothing is chosen. By mode when unset.
.Disabled()boolA picker that cannot be opened.
.Invalid()boolError styling the form did not ask for.
.Locale(…)stringThe locale the names, the week, the dates and the clock follow. The app's culture when unset.
.ShowValidation()boolFalse leaves the member's message to a Ui.Error placed elsewhere.

Ui.DatetimePickerButton

flux:datetime-picker.button

The field-shaped button in a picker's Trigger, for what the picker's own steps do not reach.

Step
Takes
What it does
.Placeholder(…)stringWhat it shows while nothing is chosen. The picker's own when unset.
.Size(…)
Ui.DatetimePickerButtonSize
Base
Sm
Xs

Each is a step of its own too, unless an HTML tag has its name.

How tall it is.
.Clearable()boolA button that empties the picker, while something is chosen. The picker's own when unset.
.Invalid()boolDraws the button as holding an error.
Confirm