Skip to content

Commit b704c8a

Browse files
Added TabSet demo based on Steve Sanderson code, but modified to use CSS Grid for layout and to demonstrate how we can have multiple RenderFragments.
Also refactored so that there are no public Params and calls to instance methods
1 parent e7f9ce8 commit b704c8a

File tree

11 files changed

+252
-2
lines changed

11 files changed

+252
-2
lines changed

BlazorTabSet/BlazorTabSet.csproj

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
<Project Sdk="Microsoft.NET.Sdk.Web">
2+
3+
<PropertyGroup>
4+
<TargetFramework>netstandard2.0</TargetFramework>
5+
<OutputType>Library</OutputType>
6+
<IsPackable>true</IsPackable>
7+
<BlazorLinkOnBuild>false</BlazorLinkOnBuild>
8+
<LangVersion>7.3</LangVersion>
9+
<Authors>Mister Magoo</Authors>
10+
<Company>MM</Company>
11+
<Description>A Blazor Component that renders a TabSet - based on Steve Sanderson demo</Description>
12+
<Copyright>Completely Free For Non-Profit</Copyright>
13+
<PackageProjectUrl>https://github.com/SQL-MisterMagoo/BlazorTest</PackageProjectUrl>
14+
<RepositoryUrl>https://github.com/SQL-MisterMagoo/BlazorTest</RepositoryUrl>
15+
<PackageTags>Blazor,TabSet,Cascade,Component</PackageTags>
16+
<Version>1.0.0</Version>
17+
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
18+
</PropertyGroup>
19+
20+
<ItemGroup>
21+
<!-- .js/.css files will be referenced via <script>/<link> tags; other content files will just be included in the app's 'dist' directory without any tags referencing them -->
22+
<EmbeddedResource Include="content\**\*.js" LogicalName="blazor:js:%(RecursiveDir)%(Filename)%(Extension)" />
23+
<EmbeddedResource Include="content\**\*.css" LogicalName="blazor:css:%(RecursiveDir)%(Filename)%(Extension)" />
24+
<EmbeddedResource Include="content\**" Exclude="**\*.js;**\*.css" LogicalName="blazor:file:%(RecursiveDir)%(Filename)%(Extension)" />
25+
</ItemGroup>
26+
27+
<ItemGroup>
28+
<None Remove="content\tabs.css" />
29+
</ItemGroup>
30+
31+
<ItemGroup>
32+
<PackageReference Include="Microsoft.AspNetCore.Blazor.Browser" Version="0.7.0" />
33+
<PackageReference Include="Microsoft.AspNetCore.Blazor.Build" Version="0.7.0" />
34+
</ItemGroup>
35+
36+
</Project>

BlazorTabSet/ITab.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
using Microsoft.AspNetCore.Blazor;
2+
3+
public interface ITab
4+
{
5+
6+
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
{
2+
"iisSettings": {
3+
"windowsAuthentication": false,
4+
"anonymousAuthentication": true,
5+
"iisExpress": {
6+
"applicationUrl": "http://localhost:60960/",
7+
"sslPort": 0
8+
}
9+
},
10+
"profiles": {
11+
"IIS Express": {
12+
"commandName": "IISExpress",
13+
"launchBrowser": true,
14+
"environmentVariables": {
15+
"ASPNETCORE_ENVIRONMENT": "Development"
16+
}
17+
},
18+
"BlazorTabSet": {
19+
"commandName": "Project",
20+
"launchBrowser": true,
21+
"environmentVariables": {
22+
"ASPNETCORE_ENVIRONMENT": "Development"
23+
},
24+
"applicationUrl": "http://localhost:60961/"
25+
}
26+
}
27+
}

BlazorTabSet/Tab.cshtml

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
@implements IDisposable
2+
@implements ITab
3+
4+
<div class="nav-tab">
5+
<a onclick=@Activate class="nav-link @TitleCssClass">
6+
@Title
7+
</a>
8+
</div>
9+
<div class="nav-tab-content @TitleCssClass">
10+
@ChildContent
11+
</div>
12+
13+
@functions {
14+
[CascadingParameter] TabSet ContainerTabSet { get; set; }
15+
[Parameter] protected string Title { get; set; }
16+
[Parameter] protected RenderFragment ChildContent { get; private set; }
17+
18+
string TitleCssClass => ContainerTabSet.ActiveTab == this ? "active" : null;
19+
20+
protected override void OnInit()
21+
{
22+
ContainerTabSet.AddTab(this);
23+
}
24+
25+
public void Dispose()
26+
{
27+
ContainerTabSet.RemoveTab(this);
28+
}
29+
30+
protected override void OnAfterRender()
31+
{
32+
base.OnAfterRender();
33+
if (ContainerTabSet.ActiveTab == this)
34+
{
35+
Activate();
36+
}
37+
}
38+
void Activate()
39+
{
40+
ContainerTabSet.SetActivateTab(this);
41+
}
42+
43+
44+
}

BlazorTabSet/TabSet.cshtml

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
<!-- Display the tab headers -->
2+
<CascadingValue Value=this>
3+
<div class="nav-tabs">
4+
@ChildContent
5+
</div>
6+
</CascadingValue>
7+
8+
<!-- Display body for only the active tab -->
9+
@*<div class="nav-tabs-body p-4">
10+
@ActiveTab?.ChildContent
11+
</div>*@
12+
13+
@functions {
14+
[Parameter] protected RenderFragment ChildContent { get; set; }
15+
[Parameter] protected RenderFragment TabTemplate { get; set; }
16+
17+
public ITab ActiveTab { get; private set; }
18+
19+
public void AddTab(ITab tab)
20+
{
21+
if (ActiveTab == null)
22+
{
23+
SetActivateTab(tab);
24+
}
25+
StateHasChanged();
26+
}
27+
28+
public void RemoveTab(ITab tab)
29+
{
30+
if (ActiveTab == tab)
31+
{
32+
SetActivateTab(null);
33+
}
34+
}
35+
36+
public void SetActivateTab(ITab tab)
37+
{
38+
if (ActiveTab != tab)
39+
{
40+
ActiveTab = tab;
41+
StateHasChanged();
42+
}
43+
}
44+
}

BlazorTabSet/content/tabs.css

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
:root {
2+
--nav-tabs--grid-column: 0;
3+
}
4+
5+
.nav-tabs {
6+
counter-reset: --nav-tabs--grid-column;
7+
display: grid;
8+
}
9+
10+
.nav-tabs .nav-link {
11+
border-color: #dee2e6 #dee2e6 #fff;
12+
border-bottom-color: #dee2e6;
13+
background-color: #f9f9f9;
14+
cursor: pointer;
15+
}
16+
17+
.nav-tabs > .nav-tab > .nav-link.active {
18+
border-top: 4px solid #e0108b !important;
19+
padding-top: 5px;
20+
border-bottom: 1px solid transparent;
21+
background-color: white;
22+
}
23+
24+
.nav-tabs > .nav-tab {
25+
counter-increment: --nav-tabs--grid-column;
26+
grid-row: 1;
27+
grid-column: var(--nav-tabs--grid-column);
28+
margin-bottom: -1px;
29+
}
30+
31+
.nav-tabs > .nav-tab-content {
32+
display: none;
33+
}
34+
35+
.nav-tabs > .nav-tab-content.active {
36+
grid-row: 2;
37+
grid-column: 1;
38+
display: block;
39+
}

BlazorTest.App/BlazorTest.App.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
<ProjectReference Include="..\BlazorFlying\BlazorFlying.csproj" />
3131
<ProjectReference Include="..\BlazorForm\BlazorForm.csproj" />
3232
<ProjectReference Include="..\BlazorSolidLogin\BlazorSolidLogin.csproj" />
33+
<ProjectReference Include="..\BlazorTabSet\BlazorTabSet.csproj" />
3334
<ProjectReference Include="..\BlazorTraffic\BlazorTraffic.csproj" />
3435
<ProjectReference Include="..\BlazorTree\BlazorTree.csproj" />
3536
<ProjectReference Include="..\Bletris\Bletris.csproj" />

BlazorTest.App/Pages/Tabs.cshtml

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
@page "/tabs"
2+
3+
<TabSet>
4+
<TabTemplate>Hello Worls</TabTemplate>
5+
<ChildContent>
6+
<Tab Title="First tab">
7+
<h4>First tab</h4>
8+
This is the first tab.
9+
</Tab>
10+
11+
@if (showSecondTab)
12+
{
13+
<Tab Title="Second">
14+
<h4>Second tab</h4>
15+
You can toggle me.
16+
</Tab>
17+
}
18+
19+
<Tab Title="Third">
20+
<h4>Third tab</h4>
21+
22+
<label>
23+
<input type="checkbox" value=@showSecondTab onchange=@showSecondTabChanged />
24+
Toggle second tab
25+
</label>
26+
</Tab>
27+
</ChildContent>
28+
</TabSet>
29+
30+
@functions
31+
{
32+
static bool showSecondTab;
33+
34+
void showSecondTabChanged(UIChangeEventArgs args)
35+
{
36+
showSecondTab = (bool)args.Value;
37+
StateHasChanged();
38+
}
39+
}

BlazorTest.App/Shared/NavMenu.cshtml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,11 @@
1616
<span class="oi oi-home" aria-hidden="true"></span> Home
1717
</NavLink>
1818
</li>
19+
<li class="nav-item px-3">
20+
<NavLink class="nav-link" href="tabs">
21+
<span class="oi oi-list-rich" aria-hidden="true"></span> TabSet demo
22+
</NavLink>
23+
</li>
1924
<li class="nav-item px-3">
2025
<NavLink class="nav-link" href="form">
2126
<span class="oi oi-list-rich" aria-hidden="true"></span> Form Without Reload

BlazorTest.App/_ViewImports.cshtml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,4 +13,5 @@
1313
@addTagHelper *, BlazorForm
1414
@addTagHelper *, BlazorTraffic
1515
@addTagHelper *, BlazorDraggable
16-
@addTagHelper *, BlazorSolidLogin
16+
@addTagHelper *, BlazorSolidLogin
17+
@addTagHelper *, BlazorTabSet

0 commit comments

Comments
 (0)