Skip to content

Commit d212ea6

Browse files
authored
feat(Tab): add Capsule style (#5642)
* feat: 增加 Capsule 模式 * doc: 更新文档 * doc: 更新示例描述文字 * test: 更新单元测试 * chore: bump version 9.4.9 * style: 精简样式
1 parent 8518bf8 commit d212ea6

File tree

9 files changed

+131
-45
lines changed

9 files changed

+131
-45
lines changed

src/BootstrapBlazor.Server/Components/Samples/Tabs.razor

+18-1
Original file line numberDiff line numberDiff line change
@@ -436,7 +436,7 @@ private void Navigation()
436436
</Tab>
437437
</DemoBlock>
438438

439-
<DemoBlock Title="@Localizer["TabsChromeStyleTitle"]" Introduction="@Localizer["TabsChromeStyleIntro"]" Name="TabStyle">
439+
<DemoBlock Title="@Localizer["TabsChromeStyleTitle"]" Introduction="@Localizer["TabsChromeStyleIntro"]" Name="Chrome">
440440
<Tab IsCard="true" ShowClose="true" TabStyle="TabStyle.Chrome">
441441
<TabItem Text="@Localizer["TabItem1Text"]" Icon="fa-solid fa-user">
442442
<div>@Localizer["TabItem1Content"]</div>
@@ -453,6 +453,23 @@ private void Navigation()
453453
</Tab>
454454
</DemoBlock>
455455

456+
<DemoBlock Title="@Localizer["TabsCapsuleStyleTitle"]" Introduction="@Localizer["TabsCapsuleStyleIntro"]" Name="Capsule">
457+
<Tab IsCard="true" ShowClose="true" TabStyle="TabStyle.Capsule">
458+
<TabItem Text="@Localizer["TabItem1Text"]" Icon="fa-solid fa-user">
459+
<div>@Localizer["TabItem1Content"]</div>
460+
</TabItem>
461+
<TabItem Text="@Localizer["TabItem2Text"]" Icon="fa-solid fa-gauge-high">
462+
<div>@Localizer["TabItem2Content"]</div>
463+
</TabItem>
464+
<TabItem Text="@Localizer["TabItem3Text"]" Icon="fa-solid fa-sitemap">
465+
<div>@Localizer["TabItem3Content"]</div>
466+
</TabItem>
467+
<TabItem Text="@Localizer["TabItem4Text"]" Icon="fa-solid fa-building-columns">
468+
<div>@Localizer["TabItem4Content"]</div>
469+
</TabItem>
470+
</Tab>
471+
</DemoBlock>
472+
456473
<AttributeTable Items="@GetAttributes()" Title="@Localizer["AttTitle"]" />
457474

458475
<MethodTable Items="@GetMethods()" Title="@Localizer["MethodTitle"]" />

src/BootstrapBlazor.Server/Locales/en-US.json

+3-1
Original file line numberDiff line numberDiff line change
@@ -2120,7 +2120,9 @@
21202120
"TabsDisabledIntro": "Disable the current <code>TabItem</code> by setting <code>IsDisabled=\"true\"</code> to prohibit click, drag, close etc.",
21212121
"TabsChromeStyleTitle": "Chrome Style",
21222122
"TabsChromeStyleIntro": "Set the Chrome browser tab style by setting <code>TabStyle=\"TabStyle.Chrome\"</code>. Currently only supports <code>Placement=\"Placement.Top\"</code> mode",
2123-
"TabAtt2TabStyle": "Set the tab style"
2123+
"TabAtt2TabStyle": "Set the tab style",
2124+
"TabsCapsuleStyleTitle": "Capsule Style",
2125+
"TabsCapsuleStyleIntro": "Set the capsule tab style by setting <code>TabStyle=\"TabStyle.Capsule\"</code>. Currently only supports <code>Placement=\"Placement.Top\"</code> <code>Placement=\"Placement.Bottom\"</code> mode"
21242126
},
21252127
"BootstrapBlazor.Server.Components.Components.DemoTabItem": {
21262128
"Info": "Reset the title of this <code>TabItem</code> by click the button",

src/BootstrapBlazor.Server/Locales/zh-CN.json

+3-1
Original file line numberDiff line numberDiff line change
@@ -2120,7 +2120,9 @@
21202120
"TabsDisabledIntro": "通过设置 <code>IsDisabled=\"true\"</code> 禁用当前 <code>TabItem</code> 禁止点击、拖动、关闭等操作",
21212121
"TabsChromeStyleTitle": "Chrome 样式",
21222122
"TabsChromeStyleIntro": "通过设置 <code>TabStyle=\"TabStyle.Chrome\"</code> 设置 Chrome 浏览器标签页样式,目前仅支持 <code>Placement=\"Placement.Top\"</code> 模式",
2123-
"TabAtt2TabStyle": "设置标签页样式"
2123+
"TabAtt2TabStyle": "设置标签页样式",
2124+
"TabsCapsuleStyleTitle": "胶囊样式",
2125+
"TabsCapsuleStyleIntro": "通过设置 <code>TabStyle=\"TabStyle.Capsule\"</code> 设置标签页为胶囊样式,目前仅支持 <code>Placement=\"Placement.Top\"</code> <code>Placement=\"Placement.Bottom\"</code> 模式"
21242126
},
21252127
"BootstrapBlazor.Server.Components.Components.DemoTabItem": {
21262128
"Info": "点击下方按钮,本 <code>TabItem</code> 标题更改为当前分钟与秒",

src/BootstrapBlazor/BootstrapBlazor.csproj

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<Project Sdk="Microsoft.NET.Sdk.Razor">
22

33
<PropertyGroup>
4-
<Version>9.4.9-beta09</Version>
4+
<Version>9.4.9</Version>
55
</PropertyGroup>
66

77
<ItemGroup>

src/BootstrapBlazor/Components/Tab/Tab.razor

+10-4
Original file line numberDiff line numberDiff line change
@@ -129,8 +129,11 @@ else
129129
<div role="tab" class="@GetClassString(item)">
130130
@RenderHeaderContent(item)
131131
</div>
132-
<i class="tab-corner tab-corner-left"></i>
133-
<i class="tab-corner tab-corner-right"></i>
132+
@if (TabStyle == TabStyle.Chrome)
133+
{
134+
<i class="tab-corner tab-corner-left"></i>
135+
<i class="tab-corner tab-corner-right"></i>
136+
}
134137
</div>;
135138

136139
RenderFragment RenderDefaultDisabledHeader(TabItem item) =>
@@ -143,8 +146,11 @@ else
143146
<a href="@item.Url" role="tab" tabindex="-1" class="@GetClassString(item)" @onclick="@(() => OnClickTabItem(item))" @onclick:preventDefault="@(!ClickTabToNavigation)" draggable="@DraggableString">
144147
@RenderHeaderContent(item)
145148
</a>
146-
<i class="tab-corner tab-corner-left"></i>
147-
<i class="tab-corner tab-corner-right"></i>
149+
@if (TabStyle == TabStyle.Chrome)
150+
{
151+
<i class="tab-corner tab-corner-left"></i>
152+
<i class="tab-corner tab-corner-right"></i>
153+
}
148154
</div>;
149155

150156
RenderFragment RenderDefaultHeader(TabItem item) =>

src/BootstrapBlazor/Components/Tab/Tab.razor.cs

+3-2
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ public partial class Tab : IHandlerException
4545
.AddClass($"tabs-{Placement.ToDescriptionString()}", Placement == Placement.Top || Placement == Placement.Right || Placement == Placement.Bottom || Placement == Placement.Left)
4646
.AddClass("tabs-vertical", Placement == Placement.Left || Placement == Placement.Right)
4747
.AddClass("tabs-chrome", TabStyle == TabStyle.Chrome)
48+
.AddClass("tabs-capsule", TabStyle == TabStyle.Capsule)
4849
.AddClassFromAttributes(AdditionalAttributes)
4950
.Build();
5051

@@ -878,9 +879,9 @@ public async Task DragItemCallback(int originIndex, int currentIndex)
878879

879880
private string? GetIdByTabItem(TabItem item) => (ShowFullScreen && item.ShowFullScreen) ? ComponentIdGenerator.Generate(item) : null;
880881

881-
private RenderFragment RenderDisabledHeaderByStyle(TabItem item) => TabStyle == TabStyle.Chrome ? RenderChromeDisabledHeader(item) : RenderDefaultDisabledHeader(item);
882+
private RenderFragment RenderDisabledHeaderByStyle(TabItem item) => TabStyle == TabStyle.Default ? RenderDefaultDisabledHeader(item) : RenderChromeDisabledHeader(item);
882883

883-
private RenderFragment RenderHeaderByStyle(TabItem item) => TabStyle == TabStyle.Chrome ? RenderChromeHeader(item) : RenderDefaultHeader(item);
884+
private RenderFragment RenderHeaderByStyle(TabItem item) => TabStyle == TabStyle.Default ? RenderDefaultHeader(item) : RenderChromeHeader(item);
884885

885886
/// <summary>
886887
/// <inheritdoc/>

src/BootstrapBlazor/Components/Tab/Tab.razor.scss

+68-34
Original file line numberDiff line numberDiff line change
@@ -488,17 +488,64 @@
488488
}
489489
}
490490

491-
.tabs-chrome {
491+
.tabs-chrome > .tabs-header,
492+
.tabs-capsule > .tabs-header {
492493
--bb-tabs-header-bg-color: var(--bs-border-color);
493494
--bb-tabs-item-hover-bg-color: rgba(var(--bs-body-color-rgb), 0.1);
494495
--bb-tabs-item-active-bg-color: var(--bs-body-bg);
495496
--bb-tabs-item-active-color: var(--bs-body-color);
496497
--bb-tabs-item-hover-color: var(--bs-body-color);
498+
--bb-tabs-item-bg-color: rgba(var(--bs-body-color-rgb), 0.08);
499+
500+
.tabs-nav {
501+
background-color: var(--bb-tabs-header-bg-color);
502+
}
503+
504+
.tabs-item-fix {
505+
border: none;
506+
}
497507

508+
.tabs-item-wrap {
509+
&:not(.active) {
510+
.tabs-item:not(.disabled) .tabs-item-body {
511+
&:hover {
512+
background-color: var(--bb-tabs-item-hover-bg-color);
513+
}
514+
}
515+
}
516+
517+
.btn-fs {
518+
padding: 0;
519+
}
520+
521+
.tabs-item {
522+
.tabs-item-body {
523+
padding: 4px 10px;
524+
display: flex;
525+
align-items: center;
526+
flex-wrap: nowrap;
527+
border-radius: 14.5px;
528+
529+
.tabs-item-text {
530+
padding: 0 .5rem;
531+
}
532+
533+
.tabs-item-close {
534+
display: flex;
535+
position: unset;
536+
width: 21px;
537+
height: 21px;
538+
border-radius: 50%;
539+
}
540+
}
541+
}
542+
}
543+
}
544+
545+
.tabs-chrome > .tabs-header {
498546
.tabs-item-wrap {
499547
overflow: hidden;
500548
position: relative;
501-
background-color: var(--bb-tabs-header-bg-color);
502549
display: flex;
503550
align-items: flex-end;
504551
flex-shrink: 0;
@@ -517,44 +564,18 @@
517564
}
518565
}
519566

520-
&:not(.active) {
521-
.tabs-item:not(.disabled) .tabs-item-body {
522-
&:hover {
523-
border-radius: 20px;
524-
background-color: var(--bb-tabs-item-hover-bg-color);
525-
}
526-
}
527-
}
528-
529567
&:not(:first-child) {
530568
margin-left: -2rem;
531569
}
532570

533571
.tabs-item {
534-
background-color: var(--bb-tabs-header-bg-color);
535572
border: none !important;
536573
border-top-left-radius: 10px;
537574
border-top-right-radius: 10px;
538575
height: 36px !important;
539576

540577
.tabs-item-body {
541-
padding: 4px 10px;
542-
display: flex;
543-
align-items: center;
544-
flex-wrap: nowrap;
545578
margin-bottom: 4px;
546-
547-
.tabs-item-text {
548-
padding: 0 .5rem;
549-
}
550-
551-
.tabs-item-close {
552-
display: flex;
553-
position: unset;
554-
width: 21px;
555-
height: 21px;
556-
border-radius: 50%;
557-
}
558579
}
559580
}
560581

@@ -592,14 +613,27 @@
592613
border-bottom-left-radius: 50%;
593614
}
594615
}
616+
}
617+
}
595618

596-
.btn-fs {
597-
padding: 0;
619+
.tabs-capsule > .tabs-header {
620+
.tabs-item-wrap {
621+
margin-left: .5rem;
622+
623+
&.active {
624+
.tabs-item {
625+
.tabs-item-body {
626+
background-color: var(--bb-tabs-item-active-bg-color);
627+
}
628+
}
598629
}
599-
}
600630

601-
> .tabs-header .tabs-item-fix {
602-
background-color: var(--bb-tabs-header-bg-color);
603-
border: none;
631+
.tabs-item {
632+
padding: 0;
633+
634+
.tabs-item-body {
635+
background-color: var(--bb-tabs-item-bg-color);
636+
}
637+
}
604638
}
605639
}

src/BootstrapBlazor/Enums/TabStyle.cs

+6-1
Original file line numberDiff line numberDiff line change
@@ -18,5 +18,10 @@ public enum TabStyle
1818
/// <summary>
1919
/// The Chrome style
2020
/// </summary>
21-
Chrome
21+
Chrome,
22+
23+
/// <summary>
24+
/// The Capsule style
25+
/// </summary>
26+
Capsule
2227
}

test/UnitTest/Components/TabTest.cs

+19
Original file line numberDiff line numberDiff line change
@@ -470,6 +470,25 @@ public async Task TabStyle_Chrome_Ok()
470470
Assert.Equal(TabStyle.Default, cut.Instance.TabStyle);
471471
}
472472

473+
[Fact]
474+
public void TabStyle_Capsule_Ok()
475+
{
476+
var cut = Context.RenderComponent<Tab>(pb =>
477+
{
478+
pb.Add(a => a.TabStyle, TabStyle.Capsule);
479+
pb.AddChildContent<TabItem>(pb =>
480+
{
481+
pb.Add(a => a.Text, "Text1");
482+
pb.Add(a => a.ChildContent, builder => builder.AddContent(0, "Test1"));
483+
pb.Add(a => a.Icon, "fa fa-fa");
484+
});
485+
});
486+
cut.Contains("tabs tabs-top tabs-capsule");
487+
cut.Contains("tabs-item-wrap active");
488+
cut.DoesNotContain("<i class=\"tab-corner tab-corner-left\"></i>");
489+
cut.DoesNotContain("<i class=\"tab-corner tab-corner-right\"></i>");
490+
}
491+
473492
[Fact]
474493
public void MenuItem_Null()
475494
{

0 commit comments

Comments
 (0)