how to create a Fluent UI custom theme for Blazor

78 Views Asked by At

So I'm looking at the design theme documentation https://www.fluentui-blazor.net/DesignTheme

It looks like in my App.razor I am meant to create my custom theme like so:

<FluentDesignTheme CustomColor="#00FFFF" StorageName="customtheme" />

Which is meant to add a record to my localstorage like so:

"customtheme" = {"primaryColor": "#00FFFF"}

but this theme does not appear in my local storage.

How can I create a custom theme and apply it to a component on demand? I don't want to change my entire app, but even if I did I couldn't get the documented examples to run in my v4.3.1 project. Any help would be greatly appreciated! Maybe someone has a sample repo I can look at for theming? After reading the documentation I'm not sure the Fluent UI theme system works or will work for my needs (creating a theme and then applying it to a component)

Thanks!

1

There are 1 best solutions below

0
Brian Parker On

Add this inside at the end of your <body/> tag.

    ...
    <script src="_content/Microsoft.FluentUI.AspNetCore.Components/js/loading-theme.js" type="text/javascript"></script>
    <loading-theme storage-name="theme"></loading-theme>
</body>

Options.razor page to set the theme.

@page "/options"
@rendermode InteractiveServer

<PageTitle>Options</PageTitle>

<FluentDesignTheme @bind-Mode="@Mode"
                   @bind-CustomColor="@CustomColor"
                   @bind-OfficeColor="@OfficeColor"
                   StorageName="theme" />
<FluentSwitch @bind-Value=UseCustomColor Label="@(UseCustomColor ? "Custom Colours": "Office Colours")" />
<FluentGrid>
    <FluentGridItem>
        <FluentSelect Label="Theme"
                      Width="250px"
                      Items="@(Enum.GetValues<DesignThemeModes>())"
                      @bind-SelectedOption="@Mode" />
    </FluentGridItem>
    @if (UseCustomColor)
    {
        <FluentGridItem>
            <FluentStack Orientation="Orientation.Vertical" VerticalGap="4">
                <FluentLabel>Color</FluentLabel>
                <input type="color" @bind=@CustomColor @bind:event="oninput" style="height:32px;margin:0;padding:0;" />
            </FluentStack>
        </FluentGridItem>
    }
    else
    {
        <FluentGridItem>
            <FluentSelect Label="Color"
                          Items="@(Enum.GetValues<OfficeColor>().Select(i => (OfficeColor?)i))"
                          Height="200px"
                          Width="250px"
                          @bind-SelectedOption="@OfficeColor">
                <OptionTemplate>
                    <FluentStack>
                        <FluentIcon Value="@(new Icons.Filled.Size20.RectangleLandscape())"
                                    Color="Color.Custom"
                                    CustomColor="@(@context.ToAttributeValue() != "default" ? context.ToAttributeValue() : "#036ac4" )" />
                        <FluentLabel>@context</FluentLabel>
                    </FluentStack>
                </OptionTemplate>
            </FluentSelect>
        </FluentGridItem>
    }
</FluentGrid>
<FluentGrid Style="margin: 30px 0px; padding: 30px; border: 1px solid var(--accent-fill-rest);">
    <FluentGridItem>
        <FluentIcon Value="@(new Icons.Regular.Size24.Airplane())" />
    </FluentGridItem>
    <FluentGridItem>
        <FluentLabel>Example of content</FluentLabel>
    </FluentGridItem>
    <FluentGridItem>
        <FluentButton Appearance="Appearance.Outline">Outline button</FluentButton>
    </FluentGridItem>
    <FluentGridItem>
        <FluentButton Appearance="Appearance.Accent">Accent button</FluentButton>
    </FluentGridItem>
</FluentGrid>
@code {
    private bool useCustomColor;
    private string? customColor = null;

    public DesignThemeModes Mode { get; set; }
    public OfficeColor? OfficeColor { get; set; }
    public string? CustomColor
    {
        get => customColor;
        set
        {
            customColor = value;
            UseCustomColor = (value is not null);
        }
    }
    public bool UseCustomColor
    {
        get => this.useCustomColor;
        set
        {
            if (value is true)
            {
                this.OfficeColor = null;
            }
            else
            {
                this.customColor = null;
            }
            this.useCustomColor = value;
        }
    }
}

@rendermode InteractiveAuto works if you place the page in the client and fluent components are configured.