@inject IJSRuntime JS
@* Dark-mode toggle. Pure JS-interop + localStorage — no DI service and no
server state. The actual theme switch happens in the browser via window.sbTheme
(wwwroot/js/theme.js); this button just drives toggle() and reflects the result.
The page-load default (no-flash) is owned by the inline pre-hydration script in
App.razor, not here. *@
@code {
/// Mirrors the browser's current theme so the glyph + aria-pressed stay in sync.
private bool _isDark;
protected override async Task OnAfterRenderAsync(bool firstRender)
{
if (!firstRender) return;
// Reflect the persisted theme once the circuit is interactive. Prerender
// has no JS runtime, so guard the call; a disconnect/blip just leaves the
// button on its default (light) glyph until the next render.
try
{
var mode = await JS.InvokeAsync("sbTheme.get");
var isDark = mode == "dark";
if (isDark != _isDark)
{
_isDark = isDark;
StateHasChanged();
}
}
catch (JSException) { }
catch (JSDisconnectedException) { }
catch (InvalidOperationException) { }
}
private async Task ToggleAsync()
{
try
{
var mode = await JS.InvokeAsync("sbTheme.toggle");
_isDark = mode == "dark";
}
catch (JSException) { }
catch (JSDisconnectedException) { }
catch (InvalidOperationException) { }
}
}