Skip to content

Commit 89e944c

Browse files
authored
feat(Tab): add ShowToolbar parameter (#5691)
* refactor: 更新方法名称 * refactor: 更新方法名称提高可读性 * refactor: 增加样式防止溢出 * style: 更新样式 * refactor: 增加 Toolbar 功能 * doc: 更新示例 * feat: 增加刷新按钮 * doc: 更新示例 * chore: 更新 Icon 依赖包 * refactor: 更新刷新按钮图标 * feat: 实现刷新逻辑 * doc: 更新注释 * refactor: 代码重构 * refactor: 更新 TabItem Body 渲染逻辑 * refactor: 精简代码 * test: 更新单元测试 * style: 调整样式 * chore: bump version 9.5.0-beta11
1 parent b7ec338 commit 89e944c

File tree

17 files changed

+356
-38
lines changed

17 files changed

+356
-38
lines changed

src/BootstrapBlazor.Server/BootstrapBlazor.Server.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@
2727
<PackageReference Include="BootstrapBlazor.BaiduOcr" Version="9.0.0" />
2828
<PackageReference Include="BootstrapBlazor.BarCode" Version="9.0.0" />
2929
<PackageReference Include="BootstrapBlazor.BarcodeGenerator" Version="9.0.0" />
30-
<PackageReference Include="BootstrapBlazor.BootstrapIcon" Version="9.0.1" />
30+
<PackageReference Include="BootstrapBlazor.BootstrapIcon" Version="9.0.2" />
3131
<PackageReference Include="BootstrapBlazor.Chart" Version="9.0.0" />
3232
<PackageReference Include="BootstrapBlazor.CherryMarkdown" Version="9.0.0" />
3333
<PackageReference Include="BootstrapBlazor.Dock" Version="9.0.0" />

src/BootstrapBlazor.Server/Components/Layout/ComponentLayout.razor

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@
3030
</div>
3131

3232
<div class="tabs-coms">
33-
<Tab IsBorderCard="true" IsLazyLoadTabItem="true" ShowFullScreen="true" TabStyle="TabStyle.Chrome" @ref="Tab">
33+
<Tab IsBorderCard="true" IsLazyLoadTabItem="true" ShowFullScreen="true" TabStyle="TabStyle.Chrome" ShowToolbar="true" @ref="Tab">
3434
<TabItem Text="Example" Icon="fa-solid fa-desktop">
3535
<CascadingValue Value="@RazorFileName" Name="RazorFileName">
3636
@Body

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

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -423,7 +423,21 @@ private void Navigation()
423423
</DemoBlock>
424424

425425
<DemoBlock Title="@Localizer["TabsDragTitle"]" Introduction="@Localizer["TabsDragIntro"]" Name="AllowDrag">
426-
<Tab IsBorderCard="true" AllowDrag="true">
426+
<Tab IsBorderCard="true" AllowDrag="true" ShowToolbar="true">
427+
<TabItem Text="@Localizer["TabItem1Text"]">
428+
<div>@Localizer["TabItem1Content"]</div>
429+
</TabItem>
430+
<TabItem Text="@Localizer["TabItem2Text"]">
431+
<div>@Localizer["TabItem2Content"]</div>
432+
</TabItem>
433+
<TabItem Text="@Localizer["TabItem3Text"]">
434+
<div>@Localizer["TabItem3Content"]</div>
435+
</TabItem>
436+
</Tab>
437+
</DemoBlock>
438+
439+
<DemoBlock Title="@Localizer["TabsDragTitle"]" Introduction="@Localizer["TabsDragIntro"]" Name="AllowDrag">
440+
<Tab IsBorderCard="true" AllowDrag="true" ShowToolbar="true">
427441
<TabItem Text="@Localizer["TabItem1Text"]">
428442
<div>@Localizer["TabItem1Content"]</div>
429443
</TabItem>
@@ -437,7 +451,7 @@ private void Navigation()
437451
</DemoBlock>
438452

439453
<DemoBlock Title="@Localizer["TabsChromeStyleTitle"]" Introduction="@Localizer["TabsChromeStyleIntro"]" Name="Chrome">
440-
<Tab IsCard="true" ShowClose="true" TabStyle="TabStyle.Chrome" AllowDrag="true">
454+
<Tab IsCard="true" ShowClose="true" TabStyle="TabStyle.Chrome" AllowDrag="true" ShowToolbar="true">
441455
<TabItem Text="@Localizer["TabItem1Text"]" Icon="fa-solid fa-user">
442456
<div>@Localizer["TabItem1Content"]</div>
443457
</TabItem>
@@ -454,9 +468,10 @@ private void Navigation()
454468
</DemoBlock>
455469

456470
<DemoBlock Title="@Localizer["TabsCapsuleStyleTitle"]" Introduction="@Localizer["TabsCapsuleStyleIntro"]" Name="Capsule">
457-
<Tab IsCard="true" ShowClose="true" TabStyle="TabStyle.Capsule" AllowDrag="true">
471+
<Tab IsCard="true" ShowClose="true" TabStyle="TabStyle.Capsule" AllowDrag="true" ShowToolbar="true">
458472
<TabItem Text="@Localizer["TabItem1Text"]" Icon="fa-solid fa-user">
459473
<div>@Localizer["TabItem1Content"]</div>
474+
<Counter></Counter>
460475
</TabItem>
461476
<TabItem Text="@Localizer["TabItem2Text"]" Icon="fa-solid fa-gauge-high">
462477
<div>@Localizer["TabItem2Content"]</div>

src/BootstrapBlazor/BootstrapBlazor.csproj

Lines changed: 1 addition & 1 deletion
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.5.0-beta10</Version>
4+
<Version>9.5.0-beta11</Version>
55
</PropertyGroup>
66

77
<ItemGroup>

src/BootstrapBlazor/Components/Tab/Tab.razor

Lines changed: 25 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -51,11 +51,11 @@ else
5151
}
5252
else if (item.IsDisabled)
5353
{
54-
@RenderDisabledHeader(item)
54+
@RenderDisabledHeaderItem(item)
5555
}
5656
else
5757
{
58-
@RenderHeader(item)
58+
@RenderHeaderItem(item)
5959
}
6060
}
6161
@if (IsCard || IsBorderCard)
@@ -73,6 +73,23 @@ else
7373
{
7474
@ButtonTemplate
7575
}
76+
@if (ShowToolbar)
77+
{
78+
<div class="tabs-nav-toolbar">
79+
@if (ShowRefreshToolbarButton)
80+
{
81+
<div class="tabs-nav-toolbar-button tabs-nav-toolbar-refresh">
82+
<TabToolbarRefreshButton Icon="@RefreshToolbarButtonIcon" OnClickAsync="OnRefreshAsync"></TabToolbarRefreshButton>
83+
</div>
84+
}
85+
@if (ShowFullscreenToolbarButton)
86+
{
87+
<div class="tabs-nav-toolbar-button tabs-nav-toolbar-fs">
88+
<FullScreenButton TargetId="@Id"></FullScreenButton>
89+
</div>
90+
}
91+
</div>
92+
}
7693
@if (ShowNavigatorButtons)
7794
{
7895
<div class="nav-link-bar right" @onclick="@ClickNextTab"><i class="@NextIcon"></i></div>
@@ -108,9 +125,7 @@ else
108125
{
109126
foreach (var item in Items)
110127
{
111-
<div @key="@item" class="@GetContentClassString(item)" id="@GetIdByTabItem(item)">
112-
@RenderTabItem(item)
113-
</div>
128+
@RenderTabItem(item)
114129
}
115130
}
116131
</CascadingValue>
@@ -124,10 +139,10 @@ else
124139
@RenderTabItemContent(item)
125140
</CascadingValue>;
126141

127-
RenderFragment RenderDisabledHeader(TabItem item) =>
142+
RenderFragment RenderDisabledHeaderItem(TabItem item) =>
128143
@<div @key="@item" class="@GetItemWrapClassString(item)">
129144
<div role="tab" class="@GetClassString(item)">
130-
@RenderHeaderContent(item)
145+
@RenderHeaderItemContent(item)
131146
</div>
132147
@if (TabStyle == TabStyle.Chrome)
133148
{
@@ -136,10 +151,10 @@ else
136151
}
137152
</div>;
138153

139-
RenderFragment RenderHeader(TabItem item) =>
154+
RenderFragment RenderHeaderItem(TabItem item) =>
140155
@<div @key="@item" class="@GetItemWrapClassString(item)" draggable="@DraggableString">
141156
<a href="@item.Url" role="tab" tabindex="-1" class="@GetClassString(item)" @onclick="@(() => OnClickTabItem(item))" @onclick:preventDefault="@(!ClickTabToNavigation)">
142-
@RenderHeaderContent(item)
157+
@RenderHeaderItemContent(item)
143158
</a>
144159
@if (TabStyle == TabStyle.Chrome)
145160
{
@@ -148,7 +163,7 @@ else
148163
}
149164
</div>;
150165

151-
RenderFragment RenderHeaderContent(TabItem item) =>
166+
RenderFragment RenderHeaderItemContent(TabItem item) =>
152167
@<div class="tabs-item-body">
153168
@if (!string.IsNullOrEmpty(item.Icon))
154169
{

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

Lines changed: 53 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -10,22 +10,18 @@
1010
namespace BootstrapBlazor.Components;
1111

1212
/// <summary>
13-
/// Tab 组件
13+
/// Tab component
1414
/// </summary>
1515
public partial class Tab : IHandlerException
1616
{
1717
private bool FirstRender { get; set; } = true;
1818

19-
private static string? GetContentClassString(TabItem item) => CssBuilder.Default("tabs-body-content")
20-
.AddClass("d-none", !item.IsActive)
21-
.Build();
22-
2319
private string? WrapClassString => CssBuilder.Default("tabs-nav-wrap")
2420
.AddClass("extend", ShouldShowExtendButtons())
2521
.Build();
2622

2723
private static string? GetItemWrapClassString(TabItem item) => CssBuilder.Default("tabs-item-wrap")
28-
.AddClass("active", item.IsActive && !item.IsDisabled)
24+
.AddClass("active", item is { IsActive: true, IsDisabled: false })
2925
.Build();
3026

3127
private string? GetClassString(TabItem item) => CssBuilder.Default("tabs-item")
@@ -58,25 +54,25 @@ public partial class Tab : IHandlerException
5854
private readonly List<TabItem> _draggedItems = new(50);
5955

6056
/// <summary>
61-
/// 获得/设置 TabItem 集合
57+
/// Gets the collection of tab items.
6258
/// </summary>
6359
public IEnumerable<TabItem> Items => TabItems;
6460

6561
private List<TabItem> TabItems => _dragged ? _draggedItems : _items;
6662

6763
/// <summary>
68-
/// 获得/设置 是否为排除地址 默认 false
64+
/// Gets or sets the excluded link. Default is false.
6965
/// </summary>
7066
private bool Excluded { get; set; }
7167

7268
/// <summary>
73-
/// 获得/设置 是否为卡片样式 默认 false
69+
/// Gets or sets whether card style. Default is false.
7470
/// </summary>
7571
[Parameter]
7672
public bool IsCard { get; set; }
7773

7874
/// <summary>
79-
/// 获得/设置 是否为带边框卡片样式 默认 false
75+
/// Gets or sets whether border card style. Default is false.
8076
/// </summary>
8177
[Parameter]
8278
public bool IsBorderCard { get; set; }
@@ -294,6 +290,30 @@ public partial class Tab : IHandlerException
294290
[Parameter]
295291
public TabStyle TabStyle { get; set; }
296292

293+
/// <summary>
294+
/// Gets or sets whether show the toolbar. Default is false.
295+
/// </summary>
296+
[Parameter]
297+
public bool ShowToolbar { get; set; }
298+
299+
/// <summary>
300+
/// Gets or sets whether show the full screen button. Default is true.
301+
/// </summary>
302+
[Parameter]
303+
public bool ShowFullscreenToolbarButton { get; set; } = true;
304+
305+
/// <summary>
306+
/// Gets or sets whether show the full screen button. Default is true.
307+
/// </summary>
308+
[Parameter]
309+
public bool ShowRefreshToolbarButton { get; set; } = true;
310+
311+
/// <summary>
312+
/// Gets or sets the refresh toolbar button icon string. Default is null.
313+
/// </summary>
314+
[Parameter]
315+
public string? RefreshToolbarButtonIcon { get; set; }
316+
297317
[CascadingParameter]
298318
private Layout? Layout { get; set; }
299319

@@ -330,6 +350,8 @@ public partial class Tab : IHandlerException
330350

331351
private string? DraggableString => AllowDrag ? "true" : null;
332352

353+
private readonly ConcurrentDictionary<TabItem, TabItemContent> _cache = [];
354+
333355
/// <summary>
334356
/// <inheritdoc/>
335357
/// </summary>
@@ -360,8 +382,16 @@ protected override void OnParametersSet()
360382
NextIcon ??= IconTheme.GetIconByKey(ComponentIcons.TabNextIcon);
361383
DropdownIcon ??= IconTheme.GetIconByKey(ComponentIcons.TabDropdownIcon);
362384
CloseIcon ??= IconTheme.GetIconByKey(ComponentIcons.TabCloseIcon);
385+
RefreshToolbarButtonIcon ??= IconTheme.GetIconByKey(ComponentIcons.TabRefreshButtonIcon);
363386

364-
AdditionalAssemblies ??= new[] { Assembly.GetEntryAssembly()! };
387+
if (AdditionalAssemblies is null)
388+
{
389+
var entryAssembly = Assembly.GetEntryAssembly();
390+
if (entryAssembly is not null)
391+
{
392+
AdditionalAssemblies = [entryAssembly];
393+
}
394+
}
365395

366396
if (Placement != Placement.Top && TabStyle == TabStyle.Chrome)
367397
{
@@ -805,7 +835,7 @@ public void SetDisabledItem(TabItem item, bool disabled)
805835
}
806836
if (TabItems.Any(i => i.IsActive) == false)
807837
{
808-
TabItems.Where(i => !i.IsDisabled).FirstOrDefault()?.SetActive(true);
838+
TabItems.FirstOrDefault(i => !i.IsDisabled)?.SetActive(true);
809839
}
810840
StateHasChanged();
811841
}
@@ -819,15 +849,15 @@ private RenderFragment RenderTabItemContent(TabItem item) => builder =>
819849

820850
if (item.IsActive)
821851
{
822-
builder.AddContent(0, item.ChildContent);
852+
builder.AddContent(0, item.RenderContent(_cache));
823853
if (IsLazyLoadTabItem)
824854
{
825855
LazyTabCache.AddOrUpdate(item, _ => true, (_, _) => true);
826856
}
827857
}
828858
else if (!IsLazyLoadTabItem || item.AlwaysLoad || LazyTabCache.TryGetValue(item, out var init) && init)
829859
{
830-
builder.AddContent(0, item.ChildContent);
860+
builder.AddContent(0, item.RenderContent(_cache));
831861
}
832862
};
833863

@@ -876,7 +906,15 @@ public async Task DragItemCallback(int originIndex, int currentIndex)
876906
}
877907
}
878908

879-
private string? GetIdByTabItem(TabItem item) => (ShowFullScreen && item.ShowFullScreen) ? ComponentIdGenerator.Generate(item) : null;
909+
private string? GetIdByTabItem(TabItem item) => ComponentIdGenerator.Generate(item);
910+
911+
private Task OnRefreshAsync()
912+
{
913+
// refresh the active tab item
914+
var item = TabItems.FirstOrDefault(i => i.IsActive);
915+
item.Refresh(_cache);
916+
return Task.CompletedTask;
917+
}
880918

881919
/// <summary>
882920
/// <inheritdoc/>

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

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -197,6 +197,7 @@
197197
}
198198

199199
.tabs .tabs-body {
200+
background-color: var(--bs-body-bg);
200201
padding: var(--bb-tabs-body-padding);
201202
flex: 1;
202203
}
@@ -232,6 +233,8 @@
232233
.tabs .tabs-item-fix {
233234
height: 100%;
234235
flex: 1;
236+
width: 1%;
237+
min-width: 0;
235238
border: 1px solid var(--bs-border-color);
236239
border-width: 0 0 1px 0;
237240
}
@@ -643,3 +646,47 @@
643646
}
644647
}
645648
}
649+
650+
.tabs {
651+
&:not(.tabs-vertical) > .tabs-header .tabs-nav-toolbar {
652+
display: flex;
653+
}
654+
655+
&.tabs-bottom > .tabs-header {
656+
.tabs-nav-toolbar {
657+
border-top: 1px solid var(--bs-border-color);
658+
}
659+
}
660+
661+
&:not(.tabs-bottom) > .tabs-header {
662+
.tabs-nav-toolbar {
663+
border-bottom: 1px solid var(--bs-border-color);
664+
}
665+
}
666+
667+
> .tabs-header {
668+
.tabs-nav-toolbar {
669+
display: none;
670+
align-items: center;
671+
height: 100%;
672+
padding: 3px 0.5rem;
673+
674+
.tabs-nav-toolbar-button {
675+
cursor: pointer;
676+
padding: 0 .75rem;
677+
height: 100%;
678+
display: flex;
679+
align-items: center;
680+
border-radius: var(--bs-border-radius);
681+
682+
&:not(.disabled):not(:disabled):hover {
683+
background-color: var(--bb-tabs-item-hover-bg-color);
684+
}
685+
686+
.btn {
687+
padding: 0;
688+
}
689+
}
690+
}
691+
}
692+
}

0 commit comments

Comments
 (0)