Theming


@inject IJSRuntime JS

@if (IsDarkModeInitialized)
{
    <PrimerIconButton Icon="@(IsDarkMode ? IconName.Moon16 : IconName.Sun16)"
                        Size="ButtonSize.Medium"
                        AriaLabelName="@AriaLabel"
                        @onclick="ToggleTheme" />
}

@code {
    private bool IsDarkMode { get; set; } = false;
    private bool IsDarkModeInitialized { get; set; } = false;
    [Parameter] public string? AriaLabel { get; set; }

    protected override async Task OnAfterRenderAsync(bool firstRender)
    {
        if (firstRender)
        {
            var saved = await JS.InvokeAsync<string>("localStorage.getItem", "theme");
            IsDarkMode = saved == "dark";
            IsDarkModeInitialized = true;
            StateHasChanged();
        }
    }

    private async Task ToggleTheme()
    {
        IsDarkMode = !IsDarkMode;
        var mode = IsDarkMode ? "dark" : "light";
        await JS.InvokeVoidAsync("setTheme", mode);
    }
}

.js


window.setTheme = function (mode) {
    document.body.setAttribute('data-color-mode', mode);
    if (mode === 'dark') {
        document.body.setAttribute('data-dark-theme', 'dark');
        document.body.removeAttribute('data-light-theme');
    } else {
        document.body.setAttribute('data-light-theme', 'light');
        document.body.removeAttribute('data-dark-theme');
    }

    localStorage.setItem('theme', mode);
};

(function () {
    const savedTheme = localStorage.getItem("theme") || "light";
    window.setTheme(savedTheme);
})();