diff --git a/DeepDrftPublic.Client/Layout/MainLayout.razor b/DeepDrftPublic.Client/Layout/MainLayout.razor
index 38dca39..bdfc432 100644
--- a/DeepDrftPublic.Client/Layout/MainLayout.razor
+++ b/DeepDrftPublic.Client/Layout/MainLayout.razor
@@ -6,6 +6,7 @@
@using Microsoft.AspNetCore.Components
@inherits LayoutComponentBase
@implements IDisposable
+@implements IAsyncDisposable
@@ -44,6 +45,7 @@
private bool _isDarkMode = false;
private bool? _lastAppliedDarkMode = null;
private PersistingComponentStateSubscription _persistingSubscription;
+ private IJSObjectReference? _themeModule;
[Inject] public required PersistentComponentState PersistentState { get; set; }
[Inject] public required DarkModeSettings DarkModeSettings { get; set; }
@@ -80,8 +82,9 @@
if (firstRender || _isDarkMode != _lastAppliedDarkMode)
{
_lastAppliedDarkMode = _isDarkMode;
- await JS.InvokeVoidAsync("eval",
- $"document.body.classList.toggle('deepdrft-theme-dark', {_isDarkMode.ToString().ToLower()})");
+ _themeModule ??= await JS.InvokeAsync(
+ "import", "./_content/DeepDrftShared.Client/js/theme/theme.js");
+ await _themeModule.InvokeVoidAsync("setBodyThemeClass", _isDarkMode);
}
}
@@ -99,6 +102,15 @@
_persistingSubscription.Dispose();
}
+ public async ValueTask DisposeAsync()
+ {
+ if (_themeModule != null)
+ {
+ try { await _themeModule.DisposeAsync(); }
+ catch (JSDisconnectedException) { /* circuit torn down */ }
+ }
+ }
+
private void ToggleAudioPlayerMinimized(bool isMinimized)
{
_audioPlayerClass = isMinimized ? "minimized" : "expanded";
diff --git a/DeepDrftShared.Client/Interop/theme/theme.ts b/DeepDrftShared.Client/Interop/theme/theme.ts
new file mode 100644
index 0000000..1566099
--- /dev/null
+++ b/DeepDrftShared.Client/Interop/theme/theme.ts
@@ -0,0 +1,15 @@
+/**
+ * theme - body-class helpers for dark-mode theme toggling.
+ *
+ * Single Responsibility: apply or remove the deepdrft-theme-dark class on
+ * document.body so that portaled MudBlazor elements (popovers, menus, selects)
+ * inherit --deepdrft-popover-surface from body.deepdrft-theme-dark rather than
+ * from :root only. Popovers portal outside the ThemeWrapperClass div, so only
+ * a body-level class can reach them.
+ */
+
+/** Toggle the deepdrft-theme-dark class on document.body.
+ * @param isDark true to add the class, false to remove it. */
+export function setBodyThemeClass(isDark: boolean): void {
+ document.body.classList.toggle('deepdrft-theme-dark', isDark);
+}