Skip to content

Commit 4c5d18f

Browse files
committed
ThemeSwitcher updates
1 parent 38037a7 commit 4c5d18f

File tree

9 files changed

+104
-182
lines changed

9 files changed

+104
-182
lines changed

BlazorBootstrap.Demo.RCL/Components/Layout/EmptyLayout.razor

Lines changed: 2 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -67,28 +67,8 @@
6767
<div class="vr d-none d-lg-flex h-100 mx-lg-2 text-white"></div>
6868
<hr class="d-lg-none my-2 text-white-50">
6969
</li>
70-
<li class="nav-item dropdown">
71-
<button class="btn btn-link nav-link py-2 px-0 px-lg-2 dropdown-toggle d-flex align-items-center" id="bd-theme" type="button" aria-expanded="false" data-bs-toggle="dropdown" data-bs-display="static" aria-label="Toggle theme (light)">
72-
<span class="blazorbootstrap-theme-indicator"><i class="bi bi-sun-fill"></i></span>
73-
<span class="d-lg-none ms-2" id="bd-theme-text">Toggle theme</span>
74-
</button>
75-
<ul class="dropdown-menu dropdown-menu-end" aria-labelledby="bd-theme-text">
76-
<li class="blazorbootstrap-theme-item px-1">
77-
<button type="button" class="dropdown-item d-flex align-items-center active rounded" data-bs-theme-value="light" aria-pressed="true" @onclick="SetLightTheme">
78-
<i class="bi bi-sun-fill me-2"></i>Light<i class="bi bi-check2 ms-auto"></i>
79-
</button>
80-
</li>
81-
<li class="blazorbootstrap-theme-item px-1">
82-
<button type="button" class="dropdown-item d-flex align-items-center rounded" data-bs-theme-value="dark" aria-pressed="false" @onclick="SetDarkTheme">
83-
<i class="bi bi-moon-stars-fill me-2"></i>Dark<i class="bi bi-check2 d-none ms-auto"></i>
84-
</button>
85-
</li>
86-
<li class="blazorbootstrap-theme-item px-1">
87-
<button type="button" class="dropdown-item d-flex align-items-center rounded" data-bs-theme-value="auto" aria-pressed="false" @onclick="SetAutoTheme">
88-
<i class="bi bi-circle-half me-2"></i>Auto<i class="bi bi-check2 d-none ms-auto"></i>
89-
</button>
90-
</li>
91-
</ul>
70+
<li class="nav-item">
71+
<ThemeSwitcher />
9272
</li>
9373
</ul>
9474
</div>

BlazorBootstrap.Demo.RCL/Components/Layout/MainLayout.razor

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33

44
<BlazorBootstrapLayout>
55
<HeaderSection>
6-
<ThemeSwitcher />
6+
<ThemeSwitcher OnThemeChanged="OnThemeChanged" />
77
</HeaderSection>
88
<SidebarSection>
99
<Sidebar2 Href="/"

BlazorBootstrap.Demo.RCL/Components/Layout/MainLayout.razor.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,4 +98,9 @@ internal override IEnumerable<NavItem> GetNavItems()
9898

9999
return navItems;
100100
}
101+
102+
private void OnThemeChanged(string themeName)
103+
{
104+
JS.InvokeVoidAsync("updateDemoCodeThemeCss", themeName);
105+
}
101106
}

BlazorBootstrap.Demo.RCL/Components/Layout/MainLayoutBase.cs

Lines changed: 0 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -20,14 +20,6 @@ public class MainLayoutBase : LayoutComponentBase
2020

2121
[Inject] protected IJSRuntime JS { get; set; } = default!;
2222

23-
protected override async Task OnAfterRenderAsync(bool firstRender)
24-
{
25-
if (firstRender)
26-
await JS.InvokeVoidAsync("initializeTheme");
27-
28-
await base.OnAfterRenderAsync(firstRender);
29-
}
30-
3123
protected override void OnInitialized()
3224
{
3325
version = $"v{Configuration["version"]}"; // example: v0.6.1
@@ -43,14 +35,6 @@ protected override void OnInitialized()
4335
base.OnInitialized();
4436
}
4537

46-
internal Task SetAutoTheme() => SetTheme("system");
47-
48-
internal Task SetDarkTheme() => SetTheme("dark");
49-
50-
internal Task SetLightTheme() => SetTheme("light");
51-
52-
internal async Task SetTheme(string themeName) => await JS.InvokeVoidAsync("setTheme", themeName);
53-
5438
internal virtual async Task<Sidebar2DataProviderResult> Sidebar2DataProvider(Sidebar2DataProviderRequest request)
5539
{
5640
if (navItems is null)

BlazorBootstrap.Demo.RCL/wwwroot/js/blazorbootstrap.demo.rcl.js

Lines changed: 19 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,9 @@
1-
async function copyToClipboard(text, dotNetHelper) {
1+
/**
2+
* Copies the provided text to the clipboard and invokes .NET methods based on the success or failure of the operation.
3+
* @param {string} text - The text to be copied to the clipboard.
4+
* @param {object} dotNetHelper - The .NET helper object to invoke methods on.
5+
*/
6+
async function copyToClipboard(text, dotNetHelper) {
27
let isCopied = true;
38

49
try {
@@ -15,13 +20,21 @@
1520
);
1621
}
1722

23+
/**
24+
* Highlights all code blocks on the page using the Prism.js library.
25+
* If the Prism.js custom class plugin is available, it prefixes all classes with 'prism-'.
26+
*/
1827
function highlightCode() {
1928
if (Prism) {
2029
Prism.plugins.customClass.prefix('prism-');
2130
Prism.highlightAll();
2231
}
2332
};
2433

34+
/**
35+
* Scrolls the page to the heading element specified by the URL hash.
36+
* If a hash is present in the URL, it finds the corresponding element by ID and scrolls it into view.
37+
*/
2538
function navigateToHeading() {
2639
if (window.location.hash) {
2740
// get hash tag in URL
@@ -34,78 +47,11 @@ function navigateToHeading() {
3447
}
3548
}
3649

37-
// THEMES
38-
const STORAGE_KEY = "blazorbootstrap-theme";
39-
const DEFAULT_THEME = "light";
40-
const SYSTEM_THEME = "system";
41-
42-
const state = {
43-
chosenTheme: SYSTEM_THEME, // light|dark|system
44-
appliedTheme: DEFAULT_THEME // light|dark
45-
};
46-
47-
const showActiveTheme = () => {
48-
let $themeIndicator = document.querySelector(".blazorbootstrap-theme-indicator>i");
49-
if ($themeIndicator) {
50-
if (state.appliedTheme === "light") {
51-
$themeIndicator.className = "bi bi-sun-fill";
52-
} else if (state.appliedTheme === "dark") {
53-
$themeIndicator.className = "bi bi-moon-stars-fill";
54-
} else {
55-
$themeIndicator.className = "bi bi-circle-half";
56-
}
57-
}
58-
59-
let $themeSwitchers = document.querySelectorAll(".blazorbootstrap-theme-item>button");
60-
if ($themeSwitchers) {
61-
$themeSwitchers.forEach((el) => {
62-
const bsThemeValue = el.dataset.bsThemeValue;
63-
const iEl = el.querySelector(".bi.bi-check2");
64-
if (state.chosenTheme === bsThemeValue) {
65-
el.classList.add("active");
66-
if (iEl)
67-
iEl.classList.remove("d-none");
68-
} else {
69-
el.classList.remove("active");
70-
if (iEl)
71-
iEl.classList.add("d-none");
72-
}
73-
});
74-
}
75-
};
76-
77-
function setTheme(theme, save = true) {
78-
state.chosenTheme = theme;
79-
state.appliedTheme = theme;
80-
81-
if (theme === SYSTEM_THEME) {
82-
state.appliedTheme = window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light';
83-
}
84-
85-
document.documentElement.setAttribute("data-bs-theme", state.appliedTheme);
86-
if (save) {
87-
window.localStorage.setItem(STORAGE_KEY, state.chosenTheme);
88-
}
89-
showActiveTheme();
90-
updateDemoCodeThemeCss(state.appliedTheme);
91-
};
92-
93-
function initializeTheme() {
94-
const localTheme = window.localStorage.getItem(STORAGE_KEY);
95-
if (localTheme) {
96-
setTheme(localTheme, false);
97-
} else {
98-
setTheme(SYSTEM_THEME);
99-
}
100-
}
101-
102-
window
103-
.matchMedia("(prefers-color-scheme: dark)")
104-
.addEventListener("change", (event) => {
105-
const theme = event.matches ? "dark" : "light";
106-
setTheme(theme);
107-
});
108-
50+
/**
51+
* Update the theme of the demo code
52+
* @param {} theme
53+
* @returns {}
54+
*/
10955
function updateDemoCodeThemeCss(theme) {
11056
if (theme === "dark") {
11157
let prismThemeLightLinkEl = document.getElementById('prismThemeLightLink');
Lines changed: 23 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,26 @@
11
@namespace BlazorBootstrap
22
@inherits BlazorBootstrapComponentBase
33

4-
<button class="btn btn-link nav-link py-2 px-0 px-lg-2 dropdown-toggle d-flex align-items-center" id="bd-theme" type="button" aria-expanded="false" data-bs-toggle="dropdown" data-bs-display="static" aria-label="Toggle theme (light)">
5-
<span class="blazorbootstrap-theme-indicator"><i class="bi bi-sun-fill"></i></span>
6-
<span class="d-lg-none ms-2" id="bd-theme-text">Toggle theme</span>
7-
</button>
8-
<ul class="dropdown-menu dropdown-menu-end" aria-labelledby="bd-theme-text">
9-
<li class="blazorbootstrap-theme-item px-1">
10-
<button type="button" class="dropdown-item d-flex align-items-center active rounded" data-bs-theme-value="light" aria-pressed="true" @onclick="SetLightTheme">
11-
<i class="bi bi-sun-fill me-2"></i>Light<i class="bi bi-check2 ms-auto"></i>
12-
</button>
13-
</li>
14-
<li class="blazorbootstrap-theme-item px-1">
15-
<button type="button" class="dropdown-item d-flex align-items-center rounded" data-bs-theme-value="dark" aria-pressed="false" @onclick="SetDarkTheme">
16-
<i class="bi bi-moon-stars-fill me-2"></i>Dark<i class="bi bi-check2 d-none ms-auto"></i>
17-
</button>
18-
</li>
19-
<li class="blazorbootstrap-theme-item px-1">
20-
<button type="button" class="dropdown-item d-flex align-items-center rounded" data-bs-theme-value="auto" aria-pressed="false" @onclick="SetAutoTheme">
21-
<i class="bi bi-circle-half me-2"></i>Auto<i class="bi bi-check2 d-none ms-auto"></i>
22-
</button>
23-
</li>
24-
</ul>
4+
<div class="dropdown">
5+
<button class="btn btn-link nav-link py-2 px-0 px-lg-2 dropdown-toggle d-flex align-items-center" id="bb-theme" type="button" aria-expanded="false" data-bs-toggle="dropdown" data-bs-display="static" aria-label="Toggle theme (light)">
6+
<span class="blazorbootstrap-theme-indicator"><i class="bi bi-sun-fill"></i></span>
7+
<span class="d-none ms-2" id="bb-theme-text">Toggle theme</span>
8+
</button>
9+
<ul class="dropdown-menu dropdown-menu-end" aria-labelledby="bb-theme-text">
10+
<li class="blazorbootstrap-theme-item px-1">
11+
<button type="button" class="dropdown-item d-flex align-items-center active rounded" data-bs-theme-value="light" aria-pressed="true" @onclick="SetLightTheme">
12+
<i class="bi bi-sun-fill me-2"></i>Light<i class="bi bi-check2 ms-auto"></i>
13+
</button>
14+
</li>
15+
<li class="blazorbootstrap-theme-item px-1">
16+
<button type="button" class="dropdown-item d-flex align-items-center rounded" data-bs-theme-value="dark" aria-pressed="false" @onclick="SetDarkTheme">
17+
<i class="bi bi-moon-stars-fill me-2"></i>Dark<i class="bi bi-check2 d-none ms-auto"></i>
18+
</button>
19+
</li>
20+
<li class="blazorbootstrap-theme-item px-1">
21+
<button type="button" class="dropdown-item d-flex align-items-center rounded" data-bs-theme-value="system" aria-pressed="false" @onclick="SetAutoTheme">
22+
<i class="bi bi-circle-half me-2"></i>Auto<i class="bi bi-check2 d-none ms-auto"></i>
23+
</button>
24+
</li>
25+
</ul>
26+
</div>

blazorbootstrap/Components/ThemeSwitcher/ThemeSwitcher.razor.cs

Lines changed: 27 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,21 +2,38 @@
22

33
public partial class ThemeSwitcher : BlazorBootstrapComponentBase
44
{
5+
6+
private DotNetObjectReference<ThemeSwitcher>? objRef;
7+
58
#region Methods
69

10+
protected override Task OnInitializedAsync()
11+
{
12+
objRef ??= DotNetObjectReference.Create(this);
13+
14+
return base.OnInitializedAsync();
15+
}
16+
717
protected override async Task OnAfterRenderAsync(bool firstRender)
818
{
919
if (firstRender)
10-
await ThemeSwitcherJsInterop.InitializeAsync();
20+
await ThemeSwitcherJsInterop.InitializeAsync(objRef);
1121

1222
await base.OnAfterRenderAsync(firstRender);
1323
}
1424

15-
internal Task SetAutoTheme() => ThemeSwitcherJsInterop.SetAutoThemeAsync();
25+
internal Task SetAutoTheme() => ThemeSwitcherJsInterop.SetAutoThemeAsync(objRef);
1626

17-
internal Task SetDarkTheme() => ThemeSwitcherJsInterop.SetDarkThemeAsync();
27+
internal Task SetDarkTheme() => ThemeSwitcherJsInterop.SetDarkThemeAsync(objRef);
1828

19-
internal Task SetLightTheme() => ThemeSwitcherJsInterop.SetLightThemeAsync();
29+
internal Task SetLightTheme() => ThemeSwitcherJsInterop.SetLightThemeAsync(objRef);
30+
31+
[JSInvokable]
32+
public async Task OnThemeChangedJS(string themeName)
33+
{
34+
if (OnThemeChanged.HasDelegate)
35+
await OnThemeChanged.InvokeAsync(themeName);
36+
}
2037

2138
#endregion
2239

@@ -25,4 +42,10 @@ protected override async Task OnAfterRenderAsync(bool firstRender)
2542
[Inject] private ThemeSwitcherJsInterop ThemeSwitcherJsInterop { get; set; } = default!;
2643

2744
#endregion
45+
46+
/// <summary>
47+
/// Fired when the theme is changed.
48+
/// </summary>
49+
[Parameter]
50+
public EventCallback<string> OnThemeChanged { get; set; }
2851
}

blazorbootstrap/Components/ThemeSwitcher/ThemeSwitcherJsInterop.cs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -28,22 +28,22 @@ public async ValueTask DisposeAsync()
2828
}
2929
}
3030

31-
public async Task InitializeAsync()
31+
public async Task InitializeAsync(DotNetObjectReference<ThemeSwitcher>? objRef)
3232
{
3333
var module = await moduleTask.Value;
34-
await module.InvokeVoidAsync("initializeTheme");
34+
await module.InvokeVoidAsync("initializeTheme", objRef);
3535
}
3636

37-
internal Task SetAutoThemeAsync() => SetThemeAsync("system");
37+
internal Task SetAutoThemeAsync(DotNetObjectReference<ThemeSwitcher>? objRef) => SetThemeAsync(objRef, "system");
3838

39-
internal Task SetDarkThemeAsync() => SetThemeAsync("dark");
39+
internal Task SetDarkThemeAsync(DotNetObjectReference<ThemeSwitcher>? objRef) => SetThemeAsync(objRef, "dark");
4040

41-
internal Task SetLightThemeAsync() => SetThemeAsync("light");
41+
internal Task SetLightThemeAsync(DotNetObjectReference<ThemeSwitcher>? objRef) => SetThemeAsync(objRef, "light");
4242

43-
internal async Task SetThemeAsync(string themeName)
43+
internal async Task SetThemeAsync(DotNetObjectReference<ThemeSwitcher>? objRef, string themeName)
4444
{
4545
var module = await moduleTask.Value;
46-
await module.InvokeVoidAsync("setTheme", themeName);
46+
await module.InvokeVoidAsync("setTheme", objRef, themeName);
4747
}
4848

4949
#endregion

0 commit comments

Comments
 (0)