Skip to content

Commit a9d1263

Browse files
authored
blazor bootstrap layout component + theme switcher - preview version (#922)
blazor bootstrap layout component + theme switcher - preview version
1 parent a618c68 commit a9d1263

File tree

12 files changed

+492
-30
lines changed

12 files changed

+492
-30
lines changed
Lines changed: 63 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,40 +1,73 @@
11
@namespace BlazorBootstrap.Demo.RCL
22
@inherits MainLayoutBase
33

4-
<div class="bb-page">
4+
<BlazorBootstrapLayout>
5+
<HeaderSection>
6+
<ThemeSwitcher />
7+
</HeaderSection>
8+
<SidebarSection>
9+
<Sidebar2 Href="/"
10+
ImageSrc="https://demos.blazorbootstrap.com/images/logo/logo-white.svg"
11+
Title="Blazor Bootstrap"
12+
BadgeText="@Version"
13+
DataProvider="Sidebar2DataProvider"
14+
WidthUnit="Unit.Px"/>
15+
</SidebarSection>
516

6-
<Sidebar2 Href="/"
7-
ImageSrc="https://demos.blazorbootstrap.com/images/logo/logo-white.svg"
8-
Title="Blazor Bootstrap"
9-
BadgeText="@Version"
10-
DataProvider="Sidebar2DataProvider"
11-
WidthUnit="Unit.Px" />
17+
<ContentSection>
18+
@Body
1219

13-
<main class="bb-scrollbar">
14-
<div class="content my-4 my-md-4 px-4">
15-
@Body
20+
<Callout Class="text-center text-bold skippy border-0" HideHeading="true">
21+
<a href="@GithubUrl" class="text-decoration-none" b-09pcjsuuk4="">
22+
<i class="bi bi-star-fill" b-09pcjsuuk4=""></i>
23+
<span b-09pcjsuuk4="">If you like Blazor Bootstrap, give it a star on GitHub!</span>
24+
<i class="bi bi-star-fill" b-09pcjsuuk4=""></i>
25+
</a>
26+
</Callout>
27+
</ContentSection>
1628

17-
<Callout Class="text-center text-bold skippy border-0" HideHeading="true">
18-
<a href="@GithubUrl" class="text-decoration-none" b-09pcjsuuk4="">
19-
<i class="bi bi-star-fill" b-09pcjsuuk4=""></i>
20-
<span b-09pcjsuuk4="">If you like Blazor Bootstrap, give it a star on GitHub!</span>
21-
<i class="bi bi-star-fill" b-09pcjsuuk4=""></i>
29+
<FooterSection>
30+
<div class="row">
31+
<div class="col-lg-4 mb-3">
32+
<a class="d-inline-flex align-items-center mb-2 text-body-emphasis text-decoration-none" href="/" aria-label="Bootstrap">
33+
<img src="/images/logo/logo-color.svg" width="40" height="32" class="d-block me-2" alt="Blazor Bootstrap">
34+
<span class="fs-5">Blazor Bootstrap</span>
2235
</a>
23-
</Callout>
36+
<ul class="list-unstyled small text-muted">
37+
<li class="mb-2">Designed and built with all the love in the world by the <strong><a href="https://www.nuget.org/packages/Blazor.Bootstrap">Blazor Bootstrap</a></strong> team with the help of our contributors.</li>
38+
<li class="mb-2">Code licensed <a href="https://github.com/vikramlearning/blazorbootstrap/blob/main/LICENSE.txt" target="_blank" rel="license noopener">Apache License 2.0</a>.</li>
39+
<li class="mb-2">Currently @Version.</li>
40+
</ul>
41+
</div>
42+
<div class="col-6 col-lg-2 offset-lg-1 mb-3">
43+
<h5>Links</h5>
44+
<ul class="list-unstyled">
45+
<li class="mb-2"><a href="/">Home</a></li>
46+
<li class="mb-2"><a href="@DocsUrl" target="_blank" rel="noopener">Docs</a></li><!--!-->
47+
<li class="mb-2"><a href="@BlogUrl" target="_blank" rel="noopener">Blog</a></li>
48+
<li class="mb-2"><a href="@GithubUrl" target="_blank" rel="noopener">GitHub</a></li>
49+
</ul>
50+
</div>
51+
<div class="col-6 col-lg-2 mb-3">
52+
<h5>Guides</h5>
53+
<ul class="list-unstyled">
54+
<li class="mb-2"><a href="/getting-started/blazor-webassembly">Getting started</a></li>
55+
<li class="mb-2"><a href="/getting-started#install-nuget-package">Install Nuget</a></li>
56+
<li class="mb-2"><a href="https://github.com/vikramlearning/blazorbootstrap-starter-templates" target="_blank">Starter templates</a></li>
57+
</ul>
58+
</div>
59+
<div class="col-6 col-lg-2 mb-3">
60+
<h5>Community</h5>
61+
<ul class="list-unstyled">
62+
<li class="mb-2"><a href="@GithubIssuesUrl" target="_blank" rel="noopener">Issues</a></li>
63+
<li class="mb-2"><a href="@GithubDiscussionsUrl" target="_blank" rel="noopener">Discussions</a></li>
64+
<li class="mb-2"><a href="@OpenCollectiveUrl" target="_blank" rel="noopener">Open Collective</a></li>
65+
<li class="mb-2"><a href="@StackoverflowUrl" target="_blank" rel="noopener">Stack Overflow</a></li>
66+
</ul>
67+
</div>
68+
<div class="col-6 col-lg-2 mb-3"></div>
2469
</div>
25-
26-
<MainLayoutBaseFooter Version="@Version"
27-
DocsUrl="@DocsUrl"
28-
BlogUrl="@BlogUrl"
29-
GithubUrl="@GithubUrl"
30-
TwitterUrl="@TwitterUrl"
31-
LinkedInUrl="@LinkedInUrl"
32-
OpenCollectiveUrl="@OpenCollectiveUrl"
33-
GithubIssuesUrl="@GithubIssuesUrl"
34-
GithubDiscussionsUrl="@GithubDiscussionsUrl"
35-
StackoverflowUrl="@StackoverflowUrl" />
36-
37-
</main>
38-
</div>
70+
</FooterSection>
71+
</BlazorBootstrapLayout>
3972

4073
<MainLayoutBaseServices />
Lines changed: 165 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,165 @@
1+
using Microsoft.Extensions.Configuration;
2+
3+
namespace BlazorBootstrap;
4+
5+
public abstract class BlazorBootstrapLayoutComponentBase : LayoutComponentBase, IDisposable, IAsyncDisposable
6+
{
7+
#region Fields and Constants
8+
9+
private bool isAsyncDisposed;
10+
11+
private bool isDisposed;
12+
13+
#endregion
14+
15+
#region Methods
16+
17+
/// <inheritdoc />
18+
protected override async Task OnAfterRenderAsync(bool firstRender)
19+
{
20+
IsRenderComplete = true;
21+
22+
await base.OnAfterRenderAsync(firstRender);
23+
}
24+
25+
/// <inheritdoc />
26+
protected override void OnInitialized()
27+
{
28+
Id ??= IdUtility.GetNextId();
29+
30+
base.OnInitialized();
31+
}
32+
33+
public static string BuildClassNames(params (string? cssClass, bool when)[] cssClassList)
34+
{
35+
var list = new HashSet<string>();
36+
37+
if (cssClassList is not null && cssClassList.Any())
38+
foreach (var (cssClass, when) in cssClassList)
39+
if (!string.IsNullOrWhiteSpace(cssClass) && when)
40+
list.Add(cssClass);
41+
42+
if (list.Any())
43+
return string.Join(" ", list);
44+
45+
return string.Empty;
46+
}
47+
48+
public static string BuildClassNames(string? userDefinedCssClass, params (string? cssClass, bool when)[] cssClassList)
49+
{
50+
var list = new HashSet<string>();
51+
52+
if (cssClassList is not null && cssClassList.Any())
53+
foreach (var (cssClass, when) in cssClassList)
54+
if (!string.IsNullOrWhiteSpace(cssClass) && when)
55+
list.Add(cssClass);
56+
57+
if (!string.IsNullOrWhiteSpace(userDefinedCssClass))
58+
list.Add(userDefinedCssClass.Trim());
59+
60+
if (list.Any())
61+
return string.Join(" ", list);
62+
63+
return string.Empty;
64+
}
65+
66+
public static string BuildStyleNames(string? userDefinedCssStyle, params (string? cssStyle, bool when)[] cssStyleList)
67+
{
68+
var list = new HashSet<string>();
69+
70+
if (cssStyleList is not null && cssStyleList.Any())
71+
foreach (var (cssStyle, when) in cssStyleList)
72+
if (!string.IsNullOrWhiteSpace(cssStyle) && when)
73+
list.Add(cssStyle);
74+
75+
if (!string.IsNullOrWhiteSpace(userDefinedCssStyle))
76+
list.Add(userDefinedCssStyle.Trim());
77+
78+
if (list.Any())
79+
return string.Join(';', list);
80+
81+
return string.Empty;
82+
}
83+
84+
/// <inheritdoc />
85+
/// <see href="https://learn.microsoft.com/en-us/dotnet/api/system.idisposable?view=net-6.0" />
86+
public void Dispose()
87+
{
88+
Dispose(true);
89+
GC.SuppressFinalize(this);
90+
}
91+
92+
/// <inheritdoc />
93+
/// <see
94+
/// href="https://learn.microsoft.com/en-us/dotnet/standard/garbage-collection/implementing-disposeasync#implement-both-dispose-and-async-dispose-patterns" />
95+
public async ValueTask DisposeAsync()
96+
{
97+
await DisposeAsyncCore(true).ConfigureAwait(false);
98+
99+
Dispose(false);
100+
GC.SuppressFinalize(this);
101+
}
102+
103+
protected virtual void Dispose(bool disposing)
104+
{
105+
if (!isDisposed)
106+
{
107+
if (disposing)
108+
{
109+
// cleanup
110+
}
111+
112+
isDisposed = true;
113+
}
114+
}
115+
116+
protected virtual ValueTask DisposeAsyncCore(bool disposing)
117+
{
118+
if (!isAsyncDisposed)
119+
{
120+
if (disposing)
121+
{
122+
// cleanup
123+
}
124+
125+
isAsyncDisposed = true;
126+
}
127+
128+
return ValueTask.CompletedTask;
129+
}
130+
131+
#endregion
132+
133+
#region Properties, Indexers
134+
135+
[Parameter(CaptureUnmatchedValues = true)] public Dictionary<string, object> AdditionalAttributes { get; set; } = default!;
136+
137+
[Parameter] public string? Class { get; set; }
138+
139+
protected virtual string? ClassNames => Class;
140+
141+
[Inject] protected IConfiguration Configuration { get; set; } = default!;
142+
143+
public ElementReference Element { get; set; }
144+
145+
[Parameter] public string? Id { get; set; }
146+
147+
protected bool IsRenderComplete { get; private set; }
148+
149+
[Inject] protected IJSRuntime JSRuntime { get; set; } = default!;
150+
151+
[Parameter] public string? Style { get; set; }
152+
153+
protected virtual string? StyleNames => Style;
154+
155+
#endregion
156+
157+
#region Other
158+
159+
~BlazorBootstrapLayoutComponentBase()
160+
{
161+
Dispose(false);
162+
}
163+
164+
#endregion
165+
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
@namespace BlazorBootstrap
2+
@inherits BlazorBootstrapLayoutComponentBase
3+
4+
<div class="@ClassNames">
5+
6+
@SidebarSection
7+
8+
<main class="bb-scrollbar">
9+
@if (HeaderSection is not null)
10+
{
11+
<div class="@HeaderSectionCssClassNames">
12+
@HeaderSection
13+
</div>
14+
}
15+
16+
<article class="@ContentSectionCssClassNames">
17+
@ContentSection
18+
</article>
19+
20+
@if (FooterSection is not null)
21+
{
22+
<div class="@FooterSectionCssClassNames">
23+
@FooterSection
24+
</div>
25+
}
26+
</main>
27+
</div>
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
namespace BlazorBootstrap;
2+
3+
public partial class BlazorBootstrapLayout : BlazorBootstrapLayoutComponentBase
4+
{
5+
#region Properties, Indexers
6+
7+
protected override string? ClassNames => BuildClassNames(Class, ("bb-page", true));
8+
9+
[Parameter] public RenderFragment? ContentSection { get; set; }
10+
[Parameter] public string? ContentSectionCssClass { get; set; }
11+
protected string? ContentSectionCssClassNames => BuildClassNames(ContentSectionCssClass, ("p-4", true));
12+
13+
[Parameter] public RenderFragment? FooterSection { get; set; }
14+
[Parameter] public string? FooterSectionCssClass { get; set; } = "bg-body-tertiary";
15+
protected string? FooterSectionCssClassNames => BuildClassNames(FooterSectionCssClass, ("bb-footer p-4", true));
16+
17+
[Parameter] public RenderFragment? HeaderSection { get; set; }
18+
[Parameter] public string? HeaderSectionCssClass { get; set; } = "d-flex justify-content-end";
19+
protected string? HeaderSectionCssClassNames => BuildClassNames(HeaderSectionCssClass, ("bb-top-row px-4", true));
20+
21+
[Parameter] public RenderFragment? SidebarSection { get; set; }
22+
23+
#endregion
24+
}

blazorbootstrap/Components/Layout/BlazorBootstrapLayout.razor.css

Whitespace-only changes.
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
@namespace BlazorBootstrap
2+
@inherits BlazorBootstrapComponentBase
3+
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>
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
namespace BlazorBootstrap;
2+
3+
public partial class ThemeSwitcher : BlazorBootstrapComponentBase
4+
{
5+
#region Methods
6+
7+
protected override async Task OnAfterRenderAsync(bool firstRender)
8+
{
9+
if (firstRender)
10+
await ThemeSwitcherJsInterop.InitializeAsync();
11+
12+
await base.OnAfterRenderAsync(firstRender);
13+
}
14+
15+
internal Task SetAutoTheme() => ThemeSwitcherJsInterop.SetAutoThemeAsync();
16+
17+
internal Task SetDarkTheme() => ThemeSwitcherJsInterop.SetDarkThemeAsync();
18+
19+
internal Task SetLightTheme() => ThemeSwitcherJsInterop.SetLightThemeAsync();
20+
21+
#endregion
22+
23+
#region Properties, Indexers
24+
25+
[Inject] private ThemeSwitcherJsInterop ThemeSwitcherJsInterop { get; set; } = default!;
26+
27+
#endregion
28+
}

blazorbootstrap/Components/ThemeSwitcher/ThemeSwitcher.razor.css

Whitespace-only changes.

0 commit comments

Comments
 (0)