Skip to content

Commit 501c014

Browse files
committed
Docs: implement theme by storing and reading from cookies
1 parent ec46b26 commit 501c014

File tree

5 files changed

+111
-21
lines changed

5 files changed

+111
-21
lines changed

Documentation/Blazorise.Docs/App.razor

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,27 @@
1313

1414
<HeadOutlet @rendermode="RenderMode.InteractiveServer" />
1515

16+
<script>
17+
(function () {
18+
const themeCookieName = "bdocs-theme";
19+
const systemCookieName = "bdocs-system";
20+
const readCookie = (name) => document.cookie.split('; ').find((row) => row.startsWith(name + '='))?.split('=')[1];
21+
const storedTheme = readCookie(themeCookieName) || "System";
22+
const systemIsDark = window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches;
23+
const shouldUseDark = storedTheme === "Dark" || (storedTheme === "System" && systemIsDark);
24+
const target = document.documentElement;
25+
26+
if (shouldUseDark) {
27+
target.setAttribute("data-bs-theme", "dark");
28+
}
29+
else {
30+
target.removeAttribute("data-bs-theme");
31+
}
32+
33+
document.cookie = `${systemCookieName}=${systemIsDark};path=/;max-age=31536000;SameSite=Lax`;
34+
})();
35+
</script>
36+
1637
<link rel="apple-touch-icon" sizes="180x180" href="/apple-touch-icon.png">
1738
<link rel="icon" type="image/png" sizes="32x32" href="/favicon-32x32.png">
1839
<link rel="icon" type="image/png" sizes="16x16" href="/favicon-16x16.png">
Lines changed: 34 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,38 @@
11
using System.Threading.Tasks;
2-
using Blazored.LocalStorage;
32
using Blazorise.Docs.Services;
4-
using Blazorise.Modules;
53
using Microsoft.AspNetCore.Components;
4+
using Microsoft.AspNetCore.Http;
5+
using Microsoft.JSInterop;
66

77
namespace Blazorise.Docs;
88

99
public partial class Routes
1010
{
11+
private const string ThemeCookieName = "bdocs-theme";
12+
private const string SystemThemeCookieName = "bdocs-system";
13+
private bool jsReady;
14+
1115
[Inject] private ThemeService ThemeService { get; set; }
12-
[Inject] private IJSUtilitiesModule JSUtilitiesModule { get; set; }
13-
[Inject] ILocalStorageService LocalStorage { get; set; }
16+
[Inject] private IHttpContextAccessor HttpContextAccessor { get; set; }
17+
[Inject] private IJSRuntime JSRuntime { get; set; }
1418

1519
protected override void OnInitialized()
1620
{
1721
ThemeService.ThemeChanged += OnThemeChanged;
1822

23+
TryLoadThemeFromCookie();
24+
1925
base.OnInitialized();
2026
}
2127

2228
protected override async Task OnAfterRenderAsync( bool firstRender )
2329
{
2430
if ( firstRender )
2531
{
26-
var theme = await LocalStorage.GetItemAsync<string>( "theme" );
27-
var systemIsDarkMode = await JSUtilitiesModule.IsSystemDarkMode();
32+
var theme = await JSRuntime.InvokeAsync<string>( "blazoriseDocs.theme.getStoredTheme" );
33+
var systemIsDarkMode = await JSRuntime.InvokeAsync<bool>( "blazoriseDocs.theme.isSystemDark" );
34+
35+
jsReady = true;
2836

2937
ThemeService.SetTheme( theme, systemIsDarkMode );
3038
}
@@ -39,17 +47,28 @@ public void Dispose()
3947

4048
async void OnThemeChanged( object sender, string theme )
4149
{
42-
if ( ThemeService.ShouldDark )
43-
{
44-
await JSUtilitiesModule.AddAttributeToBody( "data-bs-theme", "dark" );
45-
}
46-
else
47-
{
48-
await JSUtilitiesModule.RemoveAttributeFromBody( "data-bs-theme" );
49-
}
50+
if ( !jsReady )
51+
return;
5052

51-
await LocalStorage.SetItemAsync( "theme", theme );
53+
await JSRuntime.InvokeVoidAsync( "blazoriseDocs.theme.save", theme, ThemeService.SystemIsDarkMode );
5254

5355
await InvokeAsync( StateHasChanged );
5456
}
57+
58+
private void TryLoadThemeFromCookie()
59+
{
60+
var httpContext = HttpContextAccessor.HttpContext;
61+
62+
if ( httpContext is null )
63+
return;
64+
65+
if ( httpContext.Request.Cookies.TryGetValue( ThemeCookieName, out var themeFromCookie ) )
66+
{
67+
var systemIsDarkMode = httpContext.Request.Cookies.TryGetValue( SystemThemeCookieName, out var systemCookie )
68+
&& bool.TryParse( systemCookie, out var parsedSystemDark )
69+
&& parsedSystemDark;
70+
71+
ThemeService.SetTheme( themeFromCookie, systemIsDarkMode );
72+
}
73+
}
5574
}

Documentation/Blazorise.Docs/Services/ThemeService.cs

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,11 @@ namespace Blazorise.Docs.Services;
44

55
public class ThemeService
66
{
7-
const string DarkTheme = "Dark";
8-
const string LightTheme = "Light";
9-
const string SystemTheme = "System";
7+
public const string DarkTheme = "Dark";
8+
public const string LightTheme = "Light";
9+
public const string SystemTheme = "System";
1010

11-
public string CurrentTheme = LightTheme;
11+
public string CurrentTheme { get; private set; } = SystemTheme;
1212
public bool SystemIsDarkMode { get; private set; }
1313

1414
public EventHandler<string> ThemeChanged;
@@ -35,7 +35,7 @@ public void SetSystemTheme()
3535

3636
public void SetTheme( string theme, bool systemIsDarkMode )
3737
{
38-
CurrentTheme = theme;
38+
CurrentTheme = NormalizeTheme( theme );
3939
SystemIsDarkMode = systemIsDarkMode;
4040

4141
if ( ShouldDark )
@@ -51,4 +51,13 @@ public void SetTheme( string theme, bool systemIsDarkMode )
5151

5252
ThemeChanged?.Invoke( this, CurrentTheme );
5353
}
54+
55+
private static string NormalizeTheme( string theme )
56+
=> theme switch
57+
{
58+
DarkTheme => DarkTheme,
59+
LightTheme => LightTheme,
60+
SystemTheme => SystemTheme,
61+
_ => SystemTheme
62+
};
5463
}

Documentation/Blazorise.Docs/wwwroot/blazorise.docs.js

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,3 +115,44 @@ window.blazorisePRO = {
115115
}
116116
}
117117
};
118+
119+
const blazoriseDocsThemeCookieName = "bdocs-theme";
120+
const blazoriseDocsSystemCookieName = "bdocs-system";
121+
122+
window.blazoriseDocs.theme = {
123+
getStoredTheme: () => {
124+
const cookie = document.cookie.split("; ").find((row) => row.startsWith(blazoriseDocsThemeCookieName + "="));
125+
126+
return cookie ? decodeURIComponent(cookie.split("=")[1]) : null;
127+
},
128+
isSystemDark: () => window.matchMedia && window.matchMedia("(prefers-color-scheme: dark)").matches,
129+
setStoredTheme: (theme) => {
130+
const normalizedTheme = theme && theme.length ? theme : "System";
131+
132+
document.cookie = `${blazoriseDocsThemeCookieName}=${encodeURIComponent(normalizedTheme)};path=/;max-age=31536000;SameSite=Lax`;
133+
},
134+
setSystemPreference: (isDark) => {
135+
document.cookie = `${blazoriseDocsSystemCookieName}=${isDark};path=/;max-age=31536000;SameSite=Lax`;
136+
},
137+
applyTheme: (theme, systemIsDarkMode) => {
138+
const normalizedTheme = theme && theme.length ? theme : "System";
139+
const prefersDark = normalizedTheme === "Dark" || (normalizedTheme === "System" && (typeof systemIsDarkMode === "boolean" ? systemIsDarkMode : window.blazoriseDocs.theme.isSystemDark()));
140+
const body = document.body;
141+
const html = document.documentElement;
142+
143+
if (prefersDark) {
144+
html && html.setAttribute("data-bs-theme", "dark");
145+
body && body.setAttribute("data-bs-theme", "dark");
146+
} else {
147+
html && html.removeAttribute("data-bs-theme");
148+
body && body.removeAttribute("data-bs-theme");
149+
}
150+
},
151+
save: (theme, systemIsDarkMode) => {
152+
const prefersDark = typeof systemIsDarkMode === "boolean" ? systemIsDarkMode : window.blazoriseDocs.theme.isSystemDark();
153+
154+
window.blazoriseDocs.theme.setStoredTheme(theme);
155+
window.blazoriseDocs.theme.setSystemPreference(prefersDark);
156+
window.blazoriseDocs.theme.applyTheme(theme, prefersDark);
157+
}
158+
};

Documentation/Blazorise.Docs/wwwroot/blazorise.docs.min.js

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)