In this post I'll give you an overview of what's new and changed in versions 1.3 and 1.4 of the Microsoft Fluent UI for Blazor library. Me and the team were so busy with adding exciting new features that I didn't have time to blog about them earlier. I'll describe the features both from an end-user as from a code perspective.

In short, the two big end-user additions (besides some bug fixes) are:

And the repository and code changes:

  • Add missing xml comments 
  • Add FocusAsync methods to FluentInputBase 

Fluent UI System Icons support

The Fluent UI System Icons are a (still growing) collection of familiar, friendly and modern icons from Microsoft. At the moment there are more than 2020 distinct icons available in both filled and outlined versions and in various sizes. In total the collections consists of well over 11k icons in SVG format. All of them have been added to the library in an easy to use way by addition of the <FluentIcon> component. Just putting this in your .razor page:

<FluentIcon Name=@FluentIcons.Accessibility Size=IconSize.Size32 Filled=true />

Will give you this: 

Couple of things to unwrap here on the parameters used:

  • Name is a string. To make it easier to select an icon, all names have been added as constants. IntelliSense will help you find the right one. It is also using the new  .NET 6 EditorRequired feature. If you don't pass a value for the Name, Visual Studio will point that out to you in design time and raise a compile error when building.
  • Size is using an enum that holds all the possible valid sizes. Note the not all sizes are available for all icons. If you get an error at run-time, supply a different size or remove the parameter to fall back to the default size (IconSize.Size24).  
  • Filled is a bool to choose a filled (true) or a regular/outlined (false) version of an icon

Other parameters (not shown in the example above) for this component are:

  • UseAccentColor (bool). This parameter defaults to true and determines if the accent color is used for the fill or the outline when rendering the icon. When setting this to false, the icon will be rendered in black.
  • NeutralCultureName (string). Some icons offer alternative versions for specific languages. By supplying the two letter neutral language code, you can indicate that you would like to use that specific version of an icon. If there is no language specific version, the component will fall back to rendering the original version. Example:
    Neutral @FluentIcons.TextBold iconsFilled:Regular:French @FluentIcons.TextBold icons (NeutralCultureName="fr")Filled:Regular:

     

  • Slot (string). With the slot parameter you can indicate where an icon needs to be rendered in the context of another component. For example when combining a <FluentButton> with a <FluentIcon>, you can use the slot to put the icon in font of the button text: <FluentButton @onclick="HandleSearch">Search<FluentIcon Name="@FluentIcons.Search" Size="@IconSize.Size16" Filled=false Slot="start"></FluentIcon></FluentButton> (note that the icon component is inserted after the button text) . This will render:

The temporary demo site has a page to search through all the available icons and sizes.

In earlier and other libraries you will often find icons being included by means of fonts. This comes with the disadvantage that the whole font needs to be downloaded even if you are only using 1 icon. I therefore stepped away from using that method in this library and opted for taking the SVG route. Because the icons are SVG files that are stored in the wwwroot folder in a RCL (Razor Class Library), they are being treated like ordinary static files on the server. They don’t get downloaded until requested and only the icons you are actually using will be downloaded. Sounds like a win-win to me!

Design Token support

The Fluent UI Web Components are built on FAST's Adaptive UI technology, which enables design customization and personalization, while automatically maintaining accessibility. This is accomplished through setting various "Design Tokens". In previous versions of this library, the only way to manipulate the design tokens was through using the <FluentDesignSystemProvider> component. This Blazor component (and it's underlying Web Component) exposed a little over 60 variables that could be used to change things like typography, color, sizes, UI spacing, etc. FAST has been extended a while ago and now has a much more granular way of working with individual design tokens instead of just through a design system provider model. See https://docs.microsoft.com/en-us/fluent-ui/web-components/design-system/design-tokens for more information on how Design Tokens work.
In total there are now over 160 distinct tokens defined in the Adaptive UI model and as of version 1.4 of this library you can use all these in Blazor as well! The implementation has been in the works for multiple months but I think the end result is quite flexible. It allows for usage both from code as in a declarative way in your .razor pages. The two ways of working with design tokens are described below (taken from the repository readme): 

Option 1: Using Design Tokens from C# code

Given the following .razor page fragment:

<FluentButton @ref="ref1" Appearance="Appearance.Filled">A button</FluentButton>
<FluentButton @ref="ref2" Appearance="Appearance.Filled">Another button</FluentButton>
<FluentButton @ref="ref3" Appearance="Appearance.Filled">And one more</FluentButton>
<FluentButton @ref="ref4" Appearance="Appearance.Filled" @onclick=OnClick>Last button</FluentButton>

You can use Design Tokens to manipulate the styles from C# code as follows:

[Inject]
private BaseLayerLuminance BaseLayerLuminance { get; set; } = default!;

[Inject]
private AccentBaseColor AccentBaseColor { get; set; } = default!;

[Inject]
private BodyFont BodyFont { get; set; } = default!;

[Inject]
private StrokeWidth StrokeWidth { get; set; } = default!;

[Inject]
private ControlCornerRadius ControlCornerRadius { get; set; } = default!;

private FluentButton? ref1;
private FluentButton? ref2;
private FluentButton? ref3;
private FluentButton? ref4;

protected override async Task OnAfterRenderAsync(bool firstRender)
{
	if (firstRender)
	{
		//Set to dark mode
		await BaseLayerLuminance.SetValueFor(ref1!.Element, (float)0.15);

		//Set to Excel color
		await AccentBaseColor.SetValueFor(ref2!.Element, "#185ABD".ToSwatch());

		//Set the font
		await BodyFont.SetValueFor(ref3!.Element, "Comic Sans MS");

		//Set 'border' width for ref4
		await StrokeWidth.SetValueFor(ref4!.Element, 7);
		//And change conrner radius as well
		await ControlCornerRadius.SetValueFor(ref4!.Element, 15);

		StateHasChanged();
	}

}

public async Task OnClick()
{
	//Remove the wide border
	await StrokeWidth.DeleteValueFor(ref4!.Element);
}

As can be seen in the code above (with the ref4.Element), it is posible to apply multiple tokens to the same component.

For Design Tokens that work with a color value, you must call the ToSwatch() extension method on a string value or use one of the Swatch constructors. This makes sure the color is using a format that Design Tokens can handle. A Swatch has a lot of commonality with the System.Drawing.Color struct. Instead of the values of the components being between 0 and 255, in a Swatch they are expressed as a value between 0 and 1.

Important

The Design Tokens are manipulated through JavaScript interop working with an ElementReference. There is no JavaScript element until after the component is rendered. This means you can only work with the Design Tokens from code after the component has been rendered in OnAfterRenderAsync and not in any earlier lifecycle methods.

Option 2: Using Design Tokens as components

The Design Tokens can also be used as components in a .razor page directely. It looks like this:

<BaseLayerLuminance Value="(float?)0.15">
	<FluentCard BackReference="@context">
		<div class="contents">
			Dark
			<FluentButton Appearance="Appearance.Accent">Accent</FluentButton>
			<FluentButton Appearance="Appearance.Stealth">Stealth</FluentButton>
			<FluentButton Appearance="Appearance.Outline">Outline</FluentButton>
			<FluentButton Appearance="Appearance.Lightweight">Lightweight</FluentButton>
		</div>
	</FluentCard>
</BaseLayerLuminance>
 

To make this work, a link needs to be created between the Design Token component and its child components. This is done with the BackReference="@context" construct.

Note

Only one Design Token component at a time can be used this way. If you need to set more tokens, use the code approach as described in Option 1 above.

Besides these two new options, the original <FluentDesignSystemProvider> component is still there and can be used as always. There are no plans to remove this anytime soon.

XML Comments

All components and all component parameters now have xml comments. This means that tools who support this, like Visual Studio IntelliSense, will show you information about methods and parameters when editing your razor pages and code, making it a bit easier to discover and understand functionallity:

Add FocusAsync to FluentInputBase

It was not possible before to programmatically set focus to an <input> derived component like the <FluentTextField> or <FluentNumberField>. The base class <FluentInputBase> has now been extended to expose this method.

Comments


Comments are closed