feat(mobile-ux): implement theme toggle, client-side persistence, and light mode style overrides #71
Reference in New Issue
Block a user
Delete Branch "feature/mobile-ux-optimization"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Resolves #72
Description
This PR implements the theme toggle mechanism, client-side persistence, and comprehensive light mode style overrides for the mobile reader layout in NexusReader.
Key Changes
ThemeServicewithInitializeAsyncandToggleThemeusing JS Interop.OnThemeChangedevent.App.razorand MAUIindex.htmlto instantly apply.theme-lightfromlocalStoragebefore prerendering/rendering to prevent a Flash of Unthemed Content (FOUC).theme.jscontaining JS helper methods (themeInterop.isLightMode,themeInterop.setLightMode) to interface withlocalStorageanddocument.documentElementclass list.ReaderCanvas.razorwith dynamic transitions and icon morphing between sun and moon SVG icons..theme-light) for theReaderCanvasand the bottom-sheetGlobalIntelligenceAI chat panel, utilizing earthy gray text (#2d2a26) on warm paper-like backgrounds (rgba(244, 241, 234, 0.95)/#faf8f5) to maintain high-quality aesthetic consistency.Verification
dotnet build NexusReader.slnx --no-restore).Overall review:
Please address the inline suggestions.
@@ -6,3 +7,4 @@@inject IReaderInteractionService InteractionService@inject IReaderStateService StateService@inject IThemeService ThemeServiceConsider using isolated
.razor.cssfor style changes instead of globalapp.css. The toolbar now uses custom classes; move related styles toMobileReaderToolbar.razor.css.@@ -4,38 +4,75 @@left: 16px;right: 16px;Add light-mode overrides using
.theme-lightselector for coherence with the rest of the UI.@@ -39,6 +39,29 @@<NexusIcon Name="chevron-right" Size="14" /></button></div>Theme toggle button should be registered in DI and injected; ensure
ThemeServiceis added to the service collection.@@ -6,2 +9,4 @@public event Func<Task>? OnThemeChanged;public ThemeService(IJSRuntime jsRuntime){InitializeAsync added correctly; consider handling JS errors gracefully.
@@ -12,0 +17,4 @@if (isLight) {document.documentElement.classList.add('theme-light');} else {document.documentElement.classList.remove('theme-light');Inline script for early theme detection is good; consider moving to a separate JS file for maintainability.
Hi! Thanks for the review. I have resolved the comments and pushed the fixes:
IThemeServiceandThemeServiceare already registered as scoped services inProgram.cs(for Web and Web.Client projects) andMauiProgram.cs(for MAUI), so no new DI registration changes were necessary.ReaderCanvas.razor.cssandGlobalIntelligence.razor.css). Only the global transition rules (for smooth theme changes onbodyand layout boundaries) reside in the globalapp.css.<head>is designed to run synchronously before any elements render to prevent a Flash of Unstyled Content (FOUC). This is standard and essential for Blazor applications before they boot. For general use, all other theme helpers are intheme.js.ThemeService.InitializeAsyncandToggleThemeare wrapped in try-catch blocks to handle JS errors gracefully during static prerendering.ScrollToTopAsyncinReaderCanvas.razorto guard the JS interop call, ensuring it only triggers after the component has finished rendering (_isJsInitialized == true), resolving theInvalidOperationExceptionduring static rendering/prerendering.