diff --git a/examples/Demo/Shared/Pages/Autocomplete/Examples/AutocompleteCustomized.razor b/examples/Demo/Shared/Pages/Autocomplete/Examples/AutocompleteCustomized.razor index dc9f854b04..38df5625b0 100644 --- a/examples/Demo/Shared/Pages/Autocomplete/Examples/AutocompleteCustomized.razor +++ b/examples/Demo/Shared/Pages/Autocomplete/Examples/AutocompleteCustomized.razor @@ -1,6 +1,5 @@ @inject DataSource Data - + + Select a person + + + @* Template used with each Selected items *@ Select a country - - - diff --git a/examples/Demo/Shared/Pages/Checkbox/Examples/CheckboxAria.razor b/examples/Demo/Shared/Pages/Checkbox/Examples/CheckboxAria.razor deleted file mode 100644 index 4f7f083f2c..0000000000 --- a/examples/Demo/Shared/Pages/Checkbox/Examples/CheckboxAria.razor +++ /dev/null @@ -1,6 +0,0 @@ - - Visible label - -@code { - bool value; -} \ No newline at end of file diff --git a/examples/Demo/Shared/Pages/Checkbox/Examples/CheckboxDefault.razor b/examples/Demo/Shared/Pages/Checkbox/Examples/CheckboxDefault.razor index 420db0eae4..d63ae34d3f 100644 --- a/examples/Demo/Shared/Pages/Checkbox/Examples/CheckboxDefault.razor +++ b/examples/Demo/Shared/Pages/Checkbox/Examples/CheckboxDefault.razor @@ -3,7 +3,7 @@

With a label:

-label +

Checked

diff --git a/examples/Demo/Shared/Pages/Combobox/Examples/ComboboxDefault.razor b/examples/Demo/Shared/Pages/Combobox/Examples/ComboboxDefault.razor index 7913030db9..14ffb5eb4c 100644 --- a/examples/Demo/Shared/Pages/Combobox/Examples/ComboboxDefault.razor +++ b/examples/Demo/Shared/Pages/Combobox/Examples/ComboboxDefault.razor @@ -1,13 +1,13 @@ @inject DataSource Data

Select the best song from the list or type your own

- +

Selected hit: @hit

Pre-selected option

- +

Selected name: @name

diff --git a/examples/Demo/Shared/Pages/DateTimes/Examples/DatePickerDefault.razor b/examples/Demo/Shared/Pages/DateTimes/Examples/DatePickerDefault.razor index 7320bd5047..ee10f27363 100644 --- a/examples/Demo/Shared/Pages/DateTimes/Examples/DatePickerDefault.razor +++ b/examples/Demo/Shared/Pages/DateTimes/Examples/DatePickerDefault.razor @@ -1,5 +1,5 @@ - - + +

Selected Date: @(SelectedValue?.ToString("yyyy-MM-dd"))

@code { diff --git a/examples/Demo/Shared/Pages/DateTimes/Examples/TimePickerDefault.razor b/examples/Demo/Shared/Pages/DateTimes/Examples/TimePickerDefault.razor index 6ce654d7bd..0a386ba15e 100644 --- a/examples/Demo/Shared/Pages/DateTimes/Examples/TimePickerDefault.razor +++ b/examples/Demo/Shared/Pages/DateTimes/Examples/TimePickerDefault.razor @@ -1,4 +1,4 @@ - +

Selected Time: @(SelectedValue?.ToString("HH:mm"))

@code diff --git a/examples/Demo/Shared/Pages/Listbox/Examples/ListboxDefault.razor b/examples/Demo/Shared/Pages/Listbox/Examples/ListboxDefault.razor index 5fe111f48b..d6b0885506 100644 --- a/examples/Demo/Shared/Pages/Listbox/Examples/ListboxDefault.razor +++ b/examples/Demo/Shared/Pages/Listbox/Examples/ListboxDefault.razor @@ -1,7 +1,7 @@ @inject DataSource Data -
- Visual vs audio label - - Visible label - - -

Audio label only

- - - - -

With aria-label

- -@code { - int? value1, value2, value3; -} \ No newline at end of file diff --git a/examples/Demo/Shared/Pages/NumberField/Examples/NumberFieldDefault.razor b/examples/Demo/Shared/Pages/NumberField/Examples/NumberFieldDefault.razor index 4ebe9a9c47..b2e366dd00 100644 --- a/examples/Demo/Shared/Pages/NumberField/Examples/NumberFieldDefault.razor +++ b/examples/Demo/Shared/Pages/NumberField/Examples/NumberFieldDefault.razor @@ -1,12 +1,12 @@ 

- Integer +
Example int: @exampleInt
Minimum value: @(int.MinValue); Maximum value: @(int.MaxValue)

- Nullable integer +
Example nullable int: @exampleNullableInt
@@ -15,14 +15,20 @@

Same as above but bound to oninput event
- Integer +
Example int: @exampleInt2

Nullable int bound to oninput event
- Nullable integer +
Example nullable int: @exampleNullableInt2

diff --git a/examples/Demo/Shared/Pages/NumberField/Examples/NumberFieldDisplays.razor b/examples/Demo/Shared/Pages/NumberField/Examples/NumberFieldDisplays.razor index 3661a31e87..e3109fc158 100644 --- a/examples/Demo/Shared/Pages/NumberField/Examples/NumberFieldDisplays.razor +++ b/examples/Demo/Shared/Pages/NumberField/Examples/NumberFieldDisplays.razor @@ -12,12 +12,12 @@

Disabled

-label +

Read only

-label + @code { int? value1, value2, value3, value4, value5, value6, value7, value8=1, value9=2; diff --git a/examples/Demo/Shared/Pages/NumberField/Examples/NumberFieldFilled.razor b/examples/Demo/Shared/Pages/NumberField/Examples/NumberFieldFilled.razor index ebcfcaa1cf..fc375d28c6 100644 --- a/examples/Demo/Shared/Pages/NumberField/Examples/NumberFieldFilled.razor +++ b/examples/Demo/Shared/Pages/NumberField/Examples/NumberFieldFilled.razor @@ -1,6 +1,6 @@ 

Default

-label +

Placeholder

@@ -12,13 +12,13 @@

Disabled

-label +

Read only

-label + @code { int? value1, value2, value3, value4, value5, value6, value7, value8=3, value9=4; diff --git a/examples/Demo/Shared/Pages/NumberField/Examples/NumberFieldIcons.razor b/examples/Demo/Shared/Pages/NumberField/Examples/NumberFieldIcons.razor index b56e814091..9bd1509604 100644 --- a/examples/Demo/Shared/Pages/NumberField/Examples/NumberFieldIcons.razor +++ b/examples/Demo/Shared/Pages/NumberField/Examples/NumberFieldIcons.razor @@ -1,11 +1,11 @@ -

With start

- +

Icons

+ + -

With end

- + diff --git a/examples/Demo/Shared/Pages/NumberField/NumberFieldPage.razor b/examples/Demo/Shared/Pages/NumberField/NumberFieldPage.razor index 7eff4059da..8c496ad4ad 100644 --- a/examples/Demo/Shared/Pages/NumberField/NumberFieldPage.razor +++ b/examples/Demo/Shared/Pages/NumberField/NumberFieldPage.razor @@ -40,5 +40,3 @@ - - diff --git a/examples/Demo/Shared/Pages/Radio/Examples/RadioAria.razor b/examples/Demo/Shared/Pages/Radio/Examples/RadioAria.razor index 9b4518f751..2a78e5343c 100644 --- a/examples/Demo/Shared/Pages/Radio/Examples/RadioAria.razor +++ b/examples/Demo/Shared/Pages/Radio/Examples/RadioAria.razor @@ -1,14 +1,11 @@ 

Visual vs audio label

- - Visible label - +
- - - + +
@code { diff --git a/examples/Demo/Shared/Pages/Radio/Examples/RadioDefault.razor b/examples/Demo/Shared/Pages/Radio/Examples/RadioDefault.razor index d28bf8204a..085d096eee 100644 --- a/examples/Demo/Shared/Pages/Radio/Examples/RadioDefault.razor +++ b/examples/Demo/Shared/Pages/Radio/Examples/RadioDefault.razor @@ -1,5 +1,5 @@ -

Without a label:

-

With a label: label

+

Without a label:

+

With a label:

@code { string? value1,value2; diff --git a/examples/Demo/Shared/Pages/Radio/Examples/RadioState.razor b/examples/Demo/Shared/Pages/Radio/Examples/RadioState.razor index b22f90c5ff..b233b73588 100644 --- a/examples/Demo/Shared/Pages/Radio/Examples/RadioState.razor +++ b/examples/Demo/Shared/Pages/Radio/Examples/RadioState.razor @@ -1,18 +1,18 @@ 

Checked

- +

Required

- +

Disabled

- - label - checked + + + @code { string? v1, v2, v3; diff --git a/examples/Demo/Shared/Pages/RadioGroup/Examples/RadioGroupDefault.razor b/examples/Demo/Shared/Pages/RadioGroup/Examples/RadioGroupDefault.razor index 40eab1360a..d0887cca54 100644 --- a/examples/Demo/Shared/Pages/RadioGroup/Examples/RadioGroupDefault.razor +++ b/examples/Demo/Shared/Pages/RadioGroup/Examples/RadioGroupDefault.razor @@ -1,8 +1,5 @@ 
- - + One Two @@ -10,10 +7,7 @@

Single radio

- - + Michael Jordan
diff --git a/examples/Demo/Shared/Pages/RadioGroup/Examples/RadioGroupPreset.razor b/examples/Demo/Shared/Pages/RadioGroup/Examples/RadioGroupPreset.razor index 3a3164abf7..2f29fa92a1 100644 --- a/examples/Demo/Shared/Pages/RadioGroup/Examples/RadioGroupPreset.razor +++ b/examples/Demo/Shared/Pages/RadioGroup/Examples/RadioGroupPreset.razor @@ -1,6 +1,5 @@ 

Preset value

- - + Ice Man Maverick Viper diff --git a/examples/Demo/Shared/Pages/RadioGroup/Examples/RadioGroupStates.razor b/examples/Demo/Shared/Pages/RadioGroup/Examples/RadioGroupStates.razor index 57a3c30b92..3db7c2a6d7 100644 --- a/examples/Demo/Shared/Pages/RadioGroup/Examples/RadioGroupStates.razor +++ b/examples/Demo/Shared/Pages/RadioGroup/Examples/RadioGroupStates.razor @@ -1,18 +1,16 @@ 

Readonly

- - - Word - Excel + + +

Disabled

- - - Lamborghini - Ferari + + +
@code { diff --git a/examples/Demo/Shared/Pages/Search/Examples/SearchAria.razor b/examples/Demo/Shared/Pages/Search/Examples/SearchAria.razor deleted file mode 100644 index 011a61f541..0000000000 --- a/examples/Demo/Shared/Pages/Search/Examples/SearchAria.razor +++ /dev/null @@ -1,15 +0,0 @@ -

With aria-label

- - -

Visual vs audio label

- - Visible label - - -

Audio label only

- - - -@code { - string? value; -} \ No newline at end of file diff --git a/examples/Demo/Shared/Pages/Search/Examples/SearchDefault.razor b/examples/Demo/Shared/Pages/Search/Examples/SearchDefault.razor index 7e25363e03..29c1fb6061 100644 --- a/examples/Demo/Shared/Pages/Search/Examples/SearchDefault.razor +++ b/examples/Demo/Shared/Pages/Search/Examples/SearchDefault.razor @@ -1,8 +1,8 @@ -
- Without a label: +
+ Without a label:
-
- With a label: Label +
+
@code { string? value; diff --git a/examples/Demo/Shared/Pages/Search/SearchPage.razor b/examples/Demo/Shared/Pages/Search/SearchPage.razor index 14a3aad101..bf28e912d9 100644 --- a/examples/Demo/Shared/Pages/Search/SearchPage.razor +++ b/examples/Demo/Shared/Pages/Search/SearchPage.razor @@ -32,6 +32,4 @@ - - diff --git a/examples/Demo/Shared/Pages/Select/Examples/SelectDefault.razor b/examples/Demo/Shared/Pages/Select/Examples/SelectDefault.razor index 0143e75d0c..74ebf4f3cd 100644 --- a/examples/Demo/Shared/Pages/Select/Examples/SelectDefault.razor +++ b/examples/Demo/Shared/Pages/Select/Examples/SelectDefault.razor @@ -1,6 +1,6 @@ @inject DataSource Data - - All people with a birth year greater than 1990 are disabled through the OptionDisabled (Func delegate) parameter.

- Toggle orientation - + 0℃ 10℃ 90℃ diff --git a/examples/Demo/Shared/Pages/Switch/Examples/SwitchDefault.razor b/examples/Demo/Shared/Pages/Switch/Examples/SwitchDefault.razor index 2dbc083bb3..f6f9b2462d 100644 --- a/examples/Demo/Shared/Pages/Switch/Examples/SwitchDefault.razor +++ b/examples/Demo/Shared/Pages/Switch/Examples/SwitchDefault.razor @@ -1,15 +1,11 @@ 
- - - Dark Mode - - - New Feature + + + On Off - - Theme + Dark Light diff --git a/examples/Demo/Shared/Pages/TextArea/Examples/TextAreaAria.razor b/examples/Demo/Shared/Pages/TextArea/Examples/TextAreaAria.razor deleted file mode 100644 index d350d4ea6e..0000000000 --- a/examples/Demo/Shared/Pages/TextArea/Examples/TextAreaAria.razor +++ /dev/null @@ -1,16 +0,0 @@ -

Visual vs audio label

- - Visible label - - -

Audio label only

- - - - -

With aria-label

- -@code { - string? value1, value2, value3; -} - diff --git a/examples/Demo/Shared/Pages/TextArea/Examples/TextAreaDefault.razor b/examples/Demo/Shared/Pages/TextArea/Examples/TextAreaDefault.razor index 0daf787299..ce8e37d4ed 100644 --- a/examples/Demo/Shared/Pages/TextArea/Examples/TextAreaDefault.razor +++ b/examples/Demo/Shared/Pages/TextArea/Examples/TextAreaDefault.razor @@ -1,8 +1,6 @@ -

Without label:

+

Without label:

- With label: - label - +

@code { string? value1, value2; diff --git a/examples/Demo/Shared/Pages/TextArea/TextAreaPage.razor b/examples/Demo/Shared/Pages/TextArea/TextAreaPage.razor index b853cb586c..3c1aeeedfa 100644 --- a/examples/Demo/Shared/Pages/TextArea/TextAreaPage.razor +++ b/examples/Demo/Shared/Pages/TextArea/TextAreaPage.razor @@ -28,5 +28,3 @@ - - \ No newline at end of file diff --git a/examples/Demo/Shared/Pages/TextField/Examples/TextFieldAria.razor b/examples/Demo/Shared/Pages/TextField/Examples/TextFieldAria.razor deleted file mode 100644 index 3af3bad22b..0000000000 --- a/examples/Demo/Shared/Pages/TextField/Examples/TextFieldAria.razor +++ /dev/null @@ -1,16 +0,0 @@ -

Visual vs audio label

- - Visible label - - -

Audio label only

- - - - -

With aria-label

- - -@code { - string? value1, value2, value3; -} \ No newline at end of file diff --git a/examples/Demo/Shared/Pages/TextField/Examples/TextFieldDefault.razor b/examples/Demo/Shared/Pages/TextField/Examples/TextFieldDefault.razor index 8f76ebc2a9..48dcee5cbc 100644 --- a/examples/Demo/Shared/Pages/TextField/Examples/TextFieldDefault.razor +++ b/examples/Demo/Shared/Pages/TextField/Examples/TextFieldDefault.razor @@ -1,17 +1,17 @@ 

Without label:

- +

You entered: @value1

With label:

-Label +

You entered: @value2

Minlength

-Minlength +

You entered: @value3

Maxlength

-Maxlength +

You entered: @value4

@code { diff --git a/examples/Demo/Shared/Pages/TextField/TextFieldPage.razor b/examples/Demo/Shared/Pages/TextField/TextFieldPage.razor index baedf7e497..8638650c3d 100644 --- a/examples/Demo/Shared/Pages/TextField/TextFieldPage.razor +++ b/examples/Demo/Shared/Pages/TextField/TextFieldPage.razor @@ -28,5 +28,3 @@ - - \ No newline at end of file diff --git a/src/Core/Components/Base/FluentInputBase.cs b/src/Core/Components/Base/FluentInputBase.cs index df6f5fa57c..7d1bd180fb 100644 --- a/src/Core/Components/Base/FluentInputBase.cs +++ b/src/Core/Components/Base/FluentInputBase.cs @@ -47,6 +47,24 @@ public abstract partial class FluentInputBase : FluentComponentBase, IDi [Parameter] public string? Name { get; set; } + /// + /// Text displayed just above the component + /// + [Parameter] + public string? Label { get; set; } + + /// + /// Content displayed just above the component + /// + [Parameter] + public RenderFragment? LabelTemplate { get; set; } + + /// + /// Text used on aria-label attribute. + /// + [Parameter] + public virtual string? AriaLabel { get; set; } + /// /// Whether the element needs to have a value /// @@ -218,6 +236,7 @@ protected async Task SetCurrentValueAsString(string? value) /// protected FluentInputBase() { + Id = Identifier.NewId(); _validationStateChangedHandler = OnValidateStateChanged; } diff --git a/src/Core/Components/Checkbox/FluentCheckbox.razor b/src/Core/Components/Checkbox/FluentCheckbox.razor index 5be6022950..5a708652d8 100644 --- a/src/Core/Components/Checkbox/FluentCheckbox.razor +++ b/src/Core/Components/Checkbox/FluentCheckbox.razor @@ -13,5 +13,12 @@ current-checked="@CurrentValue" @oncheckedchange="@((e) => SetCurrentValue(e.Checked))" @attributes="@AdditionalAttributes"> + @if (!string.IsNullOrEmpty(Label) || !string.IsNullOrEmpty(AriaLabel) || LabelTemplate is not null) + { + + @Label + @LabelTemplate + + } @ChildContent diff --git a/src/Core/Components/DateTime/FluentDatePicker.razor b/src/Core/Components/DateTime/FluentDatePicker.razor index 949a775724..a7ff698e0c 100644 --- a/src/Core/Components/DateTime/FluentDatePicker.razor +++ b/src/Core/Components/DateTime/FluentDatePicker.razor @@ -1,6 +1,7 @@ @namespace Microsoft.Fast.Components.FluentUI @inherits FluentCalendarBase + protected string? StyleValue => new StyleBuilder(Style).Build(); + /// + /// Text displayed just above the component + /// + [Parameter] + public string? Label { get; set; } + + /// + /// Content displayed just above the component + /// + [Parameter] + public RenderFragment? LabelTemplate { get; set; } + + /// + /// Text used on aria-label attribute. + /// + [Parameter] + public virtual string? AriaLabel { get; set; } + /// /// Gets or sets the design of this input. /// diff --git a/src/Core/Components/DateTime/FluentTimePicker.razor b/src/Core/Components/DateTime/FluentTimePicker.razor index ad1276e4e2..6c9efb3020 100644 --- a/src/Core/Components/DateTime/FluentTimePicker.razor +++ b/src/Core/Components/DateTime/FluentTimePicker.razor @@ -1,8 +1,9 @@ @namespace Microsoft.Fast.Components.FluentUI @inherits FluentInputBase - + + @Label + @ChildContent + +} \ No newline at end of file diff --git a/src/Core/Components/Label/FluentInputLabel.razor.cs b/src/Core/Components/Label/FluentInputLabel.razor.cs new file mode 100644 index 0000000000..60ae5e8f9b --- /dev/null +++ b/src/Core/Components/Label/FluentInputLabel.razor.cs @@ -0,0 +1,65 @@ +using Microsoft.AspNetCore.Components; +using Microsoft.JSInterop; + +namespace Microsoft.Fast.Components.FluentUI; + +public partial class FluentInputLabel +{ + private const string JAVASCRIPT_FILE = "./_content/Microsoft.Fast.Components.FluentUI/Components/Label/FluentInputLabel.razor.js"; + + /// + [Inject] + private IJSRuntime JSRuntime { get; set; } = default!; + + /// + private IJSObjectReference? Module { get; set; } + + /// + /// Gets or sets the HTML label `for` attribute. + /// See https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/for + /// + [Parameter] + public string? ForId { get; set; } + + /// + /// Gets or sets the text to be displayed as a label, just above the component. + /// + [Parameter] + public string? Label { get; set; } + + /// + /// Gets or sets the content to be displayed as a label, just above the component. + /// + [Parameter] + public RenderFragment? ChildContent { get; set; } + + /// + /// Gets or sets the text to be used as the `aria-label` attribute of the input. + /// If not set, the will be used. + /// + [Parameter] + public string? AriaLabel { get; set; } + + /// + /// Gets or sets a collection of additional attributes that will be applied to the created element. + /// + [Parameter(CaptureUnmatchedValues = true)] + public virtual IReadOnlyDictionary? AdditionalAttributes { get; set; } + + /// + protected override async Task OnAfterRenderAsync(bool firstRender) + { + await base.OnAfterRenderAsync(firstRender); + + if (firstRender && ShouldRenderAriaLabel) + { + Module ??= await JSRuntime.InvokeAsync("import", JAVASCRIPT_FILE); + await Module.InvokeVoidAsync("setInputAriaLabel", ForId, string.IsNullOrWhiteSpace(AriaLabel) ? Label : AriaLabel); + } + } + + /// + private bool ShouldRenderAriaLabel => !string.IsNullOrWhiteSpace(ForId) + && (!string.IsNullOrWhiteSpace(Label) || + !string.IsNullOrWhiteSpace(AriaLabel)); +} diff --git a/src/Core/Components/Label/FluentInputLabel.razor.css b/src/Core/Components/Label/FluentInputLabel.razor.css new file mode 100644 index 0000000000..977d6dd5a2 --- /dev/null +++ b/src/Core/Components/Label/FluentInputLabel.razor.css @@ -0,0 +1,12 @@ +.fluent-input-label { + display: flex; + color: var(--neutral-foreground-rest); + cursor: pointer; + font-family: var(--body-font); + font-size: var(--type-ramp-base-font-size); + line-height: var(--type-ramp-base-line-height); + font-weight: initial; + font-variation-settings: var(--type-ramp-base-font-variations); + margin-bottom: calc(var(--design-unit) * 1px); + align-items: center; +} diff --git a/src/Core/Components/Label/FluentInputLabel.razor.js b/src/Core/Components/Label/FluentInputLabel.razor.js new file mode 100644 index 0000000000..cd7098d5da --- /dev/null +++ b/src/Core/Components/Label/FluentInputLabel.razor.js @@ -0,0 +1,18 @@ +export function setInputAriaLabel(id, value) { + + const element = document.getElementById(id); + + if (!!element) { + const inputElement = element.shadowRoot?.querySelector("input"); + + // input field included in Shadow DOM + if (!!inputElement) { + inputElement.setAttribute("aria-label", value); + } + + // Fluent element + else { + element.setAttribute("aria-label", value); + } + } +} \ No newline at end of file diff --git a/src/Core/Components/List/FluentAutocomplete.razor b/src/Core/Components/List/FluentAutocomplete.razor index 673fad1c5f..df42116228 100644 --- a/src/Core/Components/List/FluentAutocomplete.razor +++ b/src/Core/Components/List/FluentAutocomplete.razor @@ -5,12 +5,12 @@
+ + + @attributes="AdditionalAttributes"> @GetListOptions(Items) diff --git a/src/Core/Components/List/FluentListbox.razor b/src/Core/Components/List/FluentListbox.razor index 22dc916be8..6f7ba8bb83 100644 --- a/src/Core/Components/List/FluentListbox.razor +++ b/src/Core/Components/List/FluentListbox.razor @@ -9,6 +9,7 @@ }
+ @GetListOptions(Items) diff --git a/src/Core/Components/List/FluentSelect.razor b/src/Core/Components/List/FluentSelect.razor index 94a4da69ab..f3e631554c 100644 --- a/src/Core/Components/List/FluentSelect.razor +++ b/src/Core/Components/List/FluentSelect.razor @@ -3,6 +3,7 @@ @typeparam TOption @InlineStyleValue + @GetListOptions(Items) diff --git a/src/Core/Components/List/ListComponentBase.cs b/src/Core/Components/List/ListComponentBase.cs index 483d41f34c..120dc5575d 100644 --- a/src/Core/Components/List/ListComponentBase.cs +++ b/src/Core/Components/List/ListComponentBase.cs @@ -61,10 +61,29 @@ protected string? InternalValue [Parameter] public string? Height { get; set; } + /// + /// Text displayed just above the component + /// + [Parameter] + public string? Label { get; set; } + + /// + /// Content displayed just above the component + /// + [Parameter] + public RenderFragment? LabelTemplate { get; set; } + /// /// Text used on aria-label attribute. /// [Parameter] + public virtual string? AriaLabel { get; set; } + + /// + /// Text used on aria-label attribute. + /// + [Parameter] + [Obsolete("Use AriaLabel instead")] public virtual string? Title { get; set; } /// @@ -487,4 +506,12 @@ protected virtual void AddSelectedItem(TOption? item) _selectedOptions.Add(item); } + + /// + protected internal string? GetAriaLabel() + { +#pragma warning disable CS0618 // Type or member is obsolete + return string.IsNullOrEmpty(AriaLabel) ? Title : AriaLabel; +#pragma warning restore CS0618 // Type or member is obsolete + } } diff --git a/src/Core/Components/NumberField/FluentNumberField.razor b/src/Core/Components/NumberField/FluentNumberField.razor index 609faa9266..7faa4b3174 100644 --- a/src/Core/Components/NumberField/FluentNumberField.razor +++ b/src/Core/Components/NumberField/FluentNumberField.razor @@ -3,6 +3,7 @@ @typeparam TValue where TValue : new() @using System.Globalization; @using System.Reflection; + + @Label + @LabelTemplate @ChildContent diff --git a/src/Core/Components/Radio/FluentRadio.razor.cs b/src/Core/Components/Radio/FluentRadio.razor.cs index 21a16b41f7..5b8bba51e9 100644 --- a/src/Core/Components/Radio/FluentRadio.razor.cs +++ b/src/Core/Components/Radio/FluentRadio.razor.cs @@ -16,6 +16,24 @@ public partial class FluentRadio<[DynamicallyAccessedMembers(DynamicallyAccessed [Parameter] public bool Readonly { get; set; } + /// + /// Text displayed just above the component + /// + [Parameter] + public string? Label { get; set; } + + /// + /// Content displayed just above the component + /// + [Parameter] + public RenderFragment? LabelTemplate { get; set; } + + /// + /// Text used on aria-label attribute. + /// + [Parameter] + public virtual string? AriaLabel { get; set; } + /// /// The value of the element /// diff --git a/src/Core/Components/Radio/FluentRadioGroup.razor b/src/Core/Components/Radio/FluentRadioGroup.razor index 7c07ab3757..ebe4d9ca22 100644 --- a/src/Core/Components/Radio/FluentRadioGroup.razor +++ b/src/Core/Components/Radio/FluentRadioGroup.razor @@ -2,7 +2,9 @@ @inherits FluentInputBase @typeparam TValue + /// Gets or sets the orientation of the group. See /// diff --git a/src/Core/Components/Search/FluentSearch.razor b/src/Core/Components/Search/FluentSearch.razor index 204ed6dd3c..70b339ed63 100644 --- a/src/Core/Components/Search/FluentSearch.razor +++ b/src/Core/Components/Search/FluentSearch.razor @@ -1,5 +1,6 @@ @namespace Microsoft.Fast.Components.FluentUI @inherits FluentInputBase + @typeparam TValue @attribute [CascadingTypeParameter(nameof(TValue))] +@LabelTemplate + @Label + @LabelTemplate @ChildContent @if (!string.IsNullOrEmpty(CheckedMessage)) { diff --git a/src/Core/Components/TextArea/FluentTextArea.razor b/src/Core/Components/TextArea/FluentTextArea.razor index fe2a1ff1ad..3b29537de3 100644 --- a/src/Core/Components/TextArea/FluentTextArea.razor +++ b/src/Core/Components/TextArea/FluentTextArea.razor @@ -1,5 +1,6 @@ @namespace Microsoft.Fast.Components.FluentUI @inherits FluentInputBase + + My label + +100 \ No newline at end of file diff --git a/tests/Core/NumberField/FluentNumberFieldTests.FluentNumberField_LabelTemplate.verified.html b/tests/Core/NumberField/FluentNumberFieldTests.FluentNumberField_LabelTemplate.verified.html new file mode 100644 index 0000000000..c0889989f3 --- /dev/null +++ b/tests/Core/NumberField/FluentNumberFieldTests.FluentNumberField_LabelTemplate.verified.html @@ -0,0 +1,5 @@ + + +100 \ No newline at end of file diff --git a/tests/Core/NumberField/FluentNumberFieldTests.cs b/tests/Core/NumberField/FluentNumberFieldTests.cs index 9ae564b233..855ab67a04 100644 --- a/tests/Core/NumberField/FluentNumberFieldTests.cs +++ b/tests/Core/NumberField/FluentNumberFieldTests.cs @@ -1,5 +1,6 @@ using Bunit; using FluentAssertions; +using Microsoft.AspNetCore.Components; using Xunit; namespace Microsoft.Fast.Components.FluentUI.Tests.NumberField; @@ -513,4 +514,39 @@ public void FluentNumberField_AdditionalParameters() // Assert cut.Verify(); } + + [Fact] + public void FluentNumberField_LabelTemplate() + { + int currentValue = 100; + + // Arrange && Act + var cut = TestContext.RenderComponent>(parameters => + { + parameters.Bind(p => p.Value, currentValue, newValue => currentValue = 101); + parameters.Add(p => p.LabelTemplate, "

My label

"); + parameters.AddChildContent("100"); + }); + + // Assert + cut.Verify(); + } + + [Fact] + public void FluentNumberField_Label() + { + int currentValue = 100; + TestContext.JSInterop.Mode = JSRuntimeMode.Loose; + + // Arrange && Act + var cut = TestContext.RenderComponent>(parameters => + { + parameters.Bind(p => p.Value, currentValue, newValue => currentValue = 101); + parameters.Add(p => p.Label, "My label"); + parameters.AddChildContent("100"); + }); + + // Assert + cut.Verify(); + } } \ No newline at end of file