Alternar temas com Javascript Interop no Blazor
Para pessoas como eu, que sofrem com flashbacks toda vez que abro uma página da web, criei uma solução super simples sobre como alternar entre o modo claro e escuro usando Javascript e chamá-lo do Blazor usando Javascript Interop.
#Definindo o atributo pai
Em primeiro lugar, temos que identificar o elemento pai com um identificador, isto porque mudamos as cores dependendo do valor desse identificador.
Para fazer isso em Javascript, teríamos que executar este comando
document.documentElement.setAttribute('data-theme', 'YOUR_IDFENTIFIER');
No nosso caso, queremos ter dois identificadores para cada tipo de estilo, que são light e dark.
Criando arquivo Javascript para lidar com a lógica
Agora temos a função de atualizar o identificador, agora vamos criar um arquivo Javscript com uma função que execute essa lógica. Nosso arquivo se chamará app.js

Nesse arquivo teremos uma função que chamará o código que mencionamos anteriormente.
var toggleTheme = function (identifier) {
document.documentElement.setAttribute('data-theme', identifier);
}
Adicionando arquivo Javascript ao Blazor
Adicione o script ao aplicativo Blazor adicionando-o onde os scripts estão localizados.
<script src="~/js/app.js"></script>
Criando o serviço
Agora que temos o código Javascript, precisamos criar um serviço que se chamará ThemeToggleService.

Este serviço tratará da lógica para alternar entre o tema light e dark.
Injetando JSInterop
Para chamar qualquer Javascipt, temos que chamar o JSInterop, então temos que criar uma propriedade que irá injetar.
using Microsoft.AspNetCore.Components;
using Microsoft.JSInterop;
namespace BlazorDarkmodeToggle.Data
{
private readonly IJSRuntime jSRuntime;
public ThemeToggleService(IJSRuntime jSRuntime)
{
this.jSRuntime = jSRuntime;
}
}
Função para definir o identificador
Agora que criamos o serviço, vamos criar a função para definir o identificador, esta função irá apenas atualizar o data-theme na página.
using Microsoft.AspNetCore.Components;
using Microsoft.JSInterop;
namespace BlazorDarkmodeToggle.Data
{
public class ThemeToggleService
{
private readonly IJSRuntime jSRuntime;
public ThemeToggleService(IJSRuntime jSRuntime)
{
this.jSRuntime = jSRuntime;
}
public bool IsLightTheme { get; set; } = true;
public string GetIdentifier => IsLightTheme ? "light" : "dark";
public async Task ToggleTheme() {
IsLightTheme = !IsLightTheme;
await jSRuntime.InvokeVoidAsync("toggleTheme", GetIdentifier);
}
}
}
Adicionar serviço à inicialização
Para disponibilizar o serviço para todos os componentes e páginas, temos que adicioná-lo ao arquivo Program.cs.
builder.Services.AddSingleton<ThemeToggleService>();
Então o arquivo vai ficar assim
using BlazorDarkmodeToggle.Data;
using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components.Web;
var builder = WebApplication.CreateBuilder(args);
// Add services to the container.
builder.Services.AddRazorPages();
builder.Services.AddServerSideBlazor();
builder.Services.AddSingleton<WeatherForecastService>();
builder.Services.AddSingleton<ThemeToggleService>();
var app = builder.Build();
// Configure the HTTP request pipeline.
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error");
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.MapBlazorHub();
app.MapFallbackToPage("/_Host");
app.Run();
Lembre-se de que isso pode mudar dependendo se você usa o Blazor Server ou o Blazor WebAssembly.
Preparando o CSS
Agora que temos parte do código pronto, temos que começar a trabalhar no CSS. O que precisamos fazer é definir todas as propriedades CSS que tratam das cores CSS, plano de fundo, etc.
:root {
--background-color:#ffffff;
--text-color:#000000;
}
Depois de fazer isso, usando o identificador, podemos facilmente alternar entre os identificadores, e ele usará qualquer um dos outros valores.
[data-theme="dark"] {
--background-color: #000000;
--text-color: #ffffff;
}
Para o desvanecimento legal da animação, vamos apenas adicionar uma propriedade transition a todas, para que fique bem.
* {
transition: all 250ms;
}
Agora iremos atribuir essas variáveis a algumas classes css, para que possamos vê-las na página do Blazor.
.app-background {
background-color: var(--background-color);
width: 200px;
height: 200px;
}
.app-text {
color: var(--text-color);
}
Lembre-se de adicionar o arquivo ao aplicativo Blazor adicionando-o no head.
<link href="css/app.css" rel="stylesheet" />
Chamando do Blazor
Então, como vamos testar isso? Para simplificar, vamos apenas adicionar uma div com a classe app-background, e dentro dela terá um p com a classe app-text.Então, vamos criar uma página chamada Theme.razor na pasta Pages e adicionar algum código para isso
@page "/theme"
@using BlazorDarkmodeToggle.Data
@inject ThemeToggleService ThemeToggleService
<button class="btn btn-primary" @onclick=Toggle>Toggle theme</button>
<br />
<div class="app-background">
<p class="app-text">Hello world!</p>
</div>
@code{
public async Task Toggle()
{
await this.ThemeToggleService.ToggleTheme();
}
}
Poderíamos testar isso acessando /theme, mas também vamos adicioná-lo à barra de navegação
<div class="nav-item px-3">
<NavLink class="nav-link" href="theme">
<span class="oi oi-list-rich" aria-hidden="true"></span> Theme togle
</NavLink>
</div>
Teste

Como você pode ver, assim que alternamos as mudanças de tema, fundo e cor da fonte, agora você pode ver o quão poderoso isso é, se você realmente desenvolver a página inteira usando essas variáveis em CSS, você poderá ter temas diferentes e apenas alterná-los!
Que incrível!!
Código
Todo esse projeto está no Github e você pode encontrá-lo aqui!
Se você tiver qualquer problema ou dúvida, sinta-se à vontade para entrar em contato comigo em qualquer mídia social em @emimontesdeoca (no Twitter na verdade é @emimontesdeocaa com dois aa no final). Você também pode encontrar a maioria das minhas redes sociais no cabeçalho do blog.
Espero que você tenha gostado da postagem!