Skip to content

Commit 34e4ce5

Browse files
authored
[dev-v5] FluentTimePicker (#4216)
* Add first version of FluentTimePicker * Add Clock icon * Add a ClearValue method and call it when the user press Delete * Add type of time object * Refactoring and update doc * Add native mode (to finish) * Update TryParse * Add Attribute in shadow * fix combo example * Update doc * Rename parameter to OptionSelectedComparer * Fix global Unit Tests * Add Unit Tests * Add Unit Tests * Add Unit Tests * Add Unit Tests * Update PR comments * Add important note
1 parent 40d8424 commit 34e4ce5

30 files changed

+1168
-20
lines changed

examples/Demo/FluentUI.Demo.Client/Documentation/Components/DateTime/DatePicker/Examples/DatePickerCulture.razor

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
</div>
1111

1212
<FluentDatePicker Label="@($"Culture {SelectedCulture.DisplayName}")"
13-
Culture="SelectedCulture"
13+
Culture="@SelectedCulture"
1414
@bind-Value="@SelectedValue" />
1515

1616
<FluentDatePicker Label="Current culture"

examples/Demo/FluentUI.Demo.Client/Documentation/Components/DateTime/DatePicker/FluentDatePicker.md

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,10 @@ and to set the date format displayed in the input field.
1515

1616
## Views
1717

18-
The DatePicker can be displayed in different views: day, month, and year.
18+
The DatePicker can be displayed in different views: day, month, and year.
1919
The user can switch between these views using the title item: the month name or the year number.
2020

21-
{{ DatePickerDefault }}
21+
{{ DatePickerDefault }}
2222

2323
## DoubleClickToDate
2424

@@ -50,18 +50,16 @@ The `native` rendering style uses the default browser styles.
5050
This mode is useful when you want to use a very simple DatePicker with a **mobile device**.
5151
In this case, the mobile picker will be used. This could be useful to use the native Android or iOS date picker.
5252

53-
> [!WARNING]
54-
>
55-
> This mode is very limited in features and does not support the UI customization (`DisabledDateFunc`, `DaysTemplate`, ...).
53+
> [!WARNING] This mode is very limited in features and does not support the UI customization (`DisabledDateFunc`, `DaysTemplate`, ...).
5654
> The following parameters are ignored: `Culture`, `DayFormat`, `DisabledDateFunc`, `DisabledCheckAllDaysOfMonthYear`,
5755
> `DisabledSelectable`, `DaysTemplate`, `PickerMonthChanged`.
5856
5957
{{ DatePickerRendering }}
6058

6159
## Value type
6260

63-
The **FluentCalendar** and **FluentDatePicker** components are a generic components, so you can use it with date types such as `DateTime?`, `DateTime`, `DateOnly?` or `DateOnly`.
64-
Blazor will automatically infer the type based on the value you provide to the `Value` or `SelectedDates` parameters.
61+
The **FluentCalendar** and **FluentDatePicker** components are a generic components, so you can use it with date types such as `DateTime?`, `DateTime`, `DateOnly?` or `DateOnly`.
62+
Blazor will automatically infer the type based on the value you provide to the `Value` or `SelectedDates` parameters.
6563
You can also explicitly set the type using the generic type parameter: `TValue` (i.e. `TValue="DateOnly?"`).
6664

6765
{{ CalendarTypes }}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
@using System.Globalization
2+
3+
<FluentStack Wrap="true" HorizontalGap="64px">
4+
5+
<div style="width: 100%;">
6+
<FluentSelect Label="Select Culture"
7+
Items="@AllCultures"
8+
OptionText="@(item => $"{item.DisplayName} [{item.Name}]")"
9+
@bind-Value="@SelectedCulture" />
10+
</div>
11+
12+
<FluentTimePicker Label="@($"Culture {SelectedCulture.DisplayName}")"
13+
Culture="@SelectedCulture"
14+
@bind-Value="@SelectedValue" />
15+
16+
<FluentTimePicker Label="Current culture"
17+
@bind-Value="@SelectedValue" />
18+
</FluentStack>
19+
20+
@code
21+
{
22+
private DateTime? SelectedValue = null;
23+
private CultureInfo[] AllCultures = CultureInfo.GetCultures(CultureTypes.AllCultures)
24+
.Where(i => i.IsNeutralCulture)
25+
.OrderBy(i => i.DisplayName)
26+
.ToArray();
27+
private CultureInfo SelectedCulture = new CultureInfo("fa");
28+
}
29+
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
<div>
2+
<b>Selected time:</b> @(SelectedValue?.ToString("yyyy-MM-dd HH:mm"))
3+
</div>
4+
5+
<FluentTimePicker Label="Meeting time"
6+
DisabledTimeFunc="@(date => date?.Hour == 12)"
7+
@bind-Value="@SelectedValue" />
8+
9+
@code
10+
{
11+
DateTime? SelectedValue;
12+
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
<div>
2+
<b>Selected Time:</b> @(SelectedValue?.ToString("yyyy-MM-dd HH:mm"))
3+
</div>
4+
5+
<FluentTimePicker Label="Meeting time"
6+
RenderStyle="DatePickerRenderStyle.Native"
7+
@bind-Value="@SelectedValue" />
8+
9+
@code
10+
{
11+
DateTime? SelectedValue; // = DateTime.Today.AddHours(14);
12+
}
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
<FluentStack Wrap="true" HorizontalGap="24px">
2+
<FluentTimePicker Label="DateTime?"
3+
@bind-Value="@NullableDateTime"
4+
Message="@NullableDateTime?.ToString("yyyy-MM-dd HH:mm")"
5+
MessageCondition="@FluentFieldCondition.Always" />
6+
7+
<FluentTimePicker Label="DateTime"
8+
@bind-Value="@DateTime"
9+
Message="@DateTime.ToString("yyyy-MM-dd HH:mm")"
10+
MessageCondition="@FluentFieldCondition.Always" />
11+
12+
<FluentTimePicker Label="TimeOnly?"
13+
@bind-Value="@NullableTimeOnly"
14+
Message="@NullableTimeOnly?.ToString("HH:mm")"
15+
MessageCondition="@FluentFieldCondition.Always" />
16+
17+
<FluentTimePicker Label="TimeOnly"
18+
@bind-Value="@TimeOnly"
19+
Message="@TimeOnly.ToString("HH:mm")"
20+
MessageCondition="@FluentFieldCondition.Always" />
21+
22+
</FluentStack>
23+
24+
@code
25+
{
26+
private DateTime? NullableDateTime;
27+
private DateTime DateTime = Now;
28+
private TimeOnly? NullableTimeOnly;
29+
private TimeOnly TimeOnly = TimeOnly.FromDateTime(Now);
30+
31+
// Return the time "4pm" with no minutes/seconds component
32+
// To ensure that the TimePicker can select the current time
33+
private static DateTime Now => DateTime.Today.AddHours(16);
34+
}
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
---
2+
title: TimePicker
3+
order: 0003
4+
route: /DateTime/TimePicker
5+
---
6+
7+
# TimePicker
8+
9+
**FluentTimePicker** offers a control that's optimized for selecting a time from a
10+
drop-down list or using free-form input to select a predefined time.
11+
If the user inputs an invalid time, the field's content will be deleted when it losses focus.
12+
13+
You can use the `Culture` parameter to display the time in different format patterns;
14+
and to set the time format displayed in the input field.
15+
16+
**Important**
17+
18+
By default, **FluentTimePicker** displays a list of **predefined** times, ranging from `StartHour` 8:00 a.m. to `EndHour` 6:00 p.m. in 15-minute `Increment`.
19+
You can customize these parameters to fit your requirements.
20+
If you want the user to be able **to enter any time** (any hour or any minute), you must enable the mode `RenderStyle="Native"`.
21+
22+
## Default
23+
24+
The TimePicker allows users to select a time value: `<FluentTimePicker @bind-Value="@SelectedValue" />`
25+
26+
{{ TimePickerDefault }}
27+
28+
When you bind a DateTime value to the TimePicker, the date part is ignored in the input field.
29+
But the date part is preserved in the bound value.
30+
For nullable DateTime (`DateTime?`), the value will be deleted when the user clears the input field
31+
by using `Delete` key.
32+
33+
## Culture
34+
35+
You can set the culture of the TimePicker to display the hours and minutes in different
36+
formats. Use the `Culture` parameter to set the desired time format.
37+
We are using the `Culture.DateTimeFormat.ShortTimePattern` property to display the time with the correct pattern (e.g. `HH:mm`).
38+
39+
Example: `Culture="@(new CultureInfo("fr"))"` will display the time in French (`HH:mm`).
40+
41+
{{ TimePickerCulture }}
42+
43+
## RenderStyle
44+
45+
The TimePicker can be rendered in different modes: `FluentUI`, `Native`.
46+
47+
The `FluentUI` rendering style uses the Fluent UI styles and components.
48+
This mode provides a consistent look and feel with other Fluent UI components.
49+
This mode provides all the features of the component.
50+
51+
The `Native` rendering style uses the default browser styles.
52+
This mode is useful when you want to use a very simple TimePicker with a **mobile device**.
53+
In this case, the mobile picker will be used. This could be useful to use the native Android or iOS date picker.
54+
55+
> [!WARNING] This mode is very limited in features and does not support the UI customization.
56+
> The following parameters are ignored: `Culture`, `StartHour`, `EndHour`, `Increment`,`DisabledTimeFunc`.
57+
58+
{{ TimePickerRendering }}
59+
60+
[!NOTE] Active HTML form controls like `<input type="time">` have limited styling capabilities.
61+
The **clock icon** is part of the browser's internal implementation and is generally not affected by CSS styling, including **dark mode** styles.
62+
63+
## Value type
64+
65+
The **FluentTimePicker** component is a generic component, so you can use it with date types such as `DateTime?`, `DateTime`, `TimeOnly?` or `TimeOnly`.
66+
Blazor will automatically infer the type based on the value you provide to the `Value` parameters.
67+
You can also explicitly set the type using the generic type parameter: `TValue` (i.e. `TValue="TimeOnly?"`).
68+
69+
{{ TimePickerTypes }}
70+
71+
## API FluentTimePicker
72+
73+
{{ API Type=FluentTimePicker<DateTime> }}
74+
75+
> [!NOTE] The `Width` parameter is not yet developed.

examples/Demo/FluentUI.Demo.Client/Documentation/Components/List/Combobox/Examples/ComboboxDefault.razor

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@
22
TOption="@SampleData.Olympics2024.Country"
33
Placeholder="Select your countries"
44
Multiple="true"
5-
OptionText="@(i => i.Name)"
6-
OptionValue="@(i => i.Code)"
5+
OptionText="@(i => i?.Name)"
6+
OptionValue="@(i => i?.Code)"
77
Items="@Countries"
88
@bind-SelectedItems="@SelectedCountries">
99
<FreeOption>

examples/Demo/FluentUI.Demo.Client/Documentation/Components/List/Combobox/FluentCombobox.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,8 @@ See a similar example on the [FluentSelect](/List/Select#customize-the-items) pa
5858

5959
{{ API Type=FluentCombobox }}
6060

61+
> [!NOTE] The `Width` parameter is not yet implemented.
62+
6163
## API FluentOption
6264

6365
{{ API Type=FluentOption }}

examples/Demo/FluentUI.Demo.Client/Documentation/Components/List/Select/FluentSelect.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,8 @@ If you have a very large number of items, you should use the **FluentAutocomplet
9191

9292
{{ API Type=FluentSelect }}
9393

94+
> [!NOTE] The `Width` parameter is not yet implemented.
95+
9496
## API FluentOption
9597

9698
{{ API Type=FluentOption }}

0 commit comments

Comments
 (0)