diff --git a/src/BootstrapBlazor/Components/Layout/Layout.razor.cs b/src/BootstrapBlazor/Components/Layout/Layout.razor.cs index 617254755b1..1938cd1ed95 100644 --- a/src/BootstrapBlazor/Components/Layout/Layout.razor.cs +++ b/src/BootstrapBlazor/Components/Layout/Layout.razor.cs @@ -33,7 +33,7 @@ public partial class Layout : IHandlerException /// Gets or sets the template of the toolbar button. Default is null. /// [Parameter] - public RenderFragment? ToolbarTemplate { get; set; } + public RenderFragment? ToolbarTemplate { get; set; } /// /// Gets or sets whether show the full screen button. Default is true. diff --git a/src/BootstrapBlazor/Components/Layout/Layout.razor.scss b/src/BootstrapBlazor/Components/Layout/Layout.razor.scss index 334bced2613..1784445d252 100644 --- a/src/BootstrapBlazor/Components/Layout/Layout.razor.scss +++ b/src/BootstrapBlazor/Components/Layout/Layout.razor.scss @@ -49,14 +49,6 @@ .layout-main { min-height: calc(var(--bb-layout-height) - var(--bb-layout-header-height) - var(--bb-layout-footer-height)); - - > .tabs, - > .bb-cm-zone > .tabs { - margin: -1rem; - border: none; - border-radius: unset; - min-height: calc(100% + 2rem); - } } } diff --git a/src/BootstrapBlazor/Components/Tab/Tab.razor b/src/BootstrapBlazor/Components/Tab/Tab.razor index d86840e722c..d18439f1a19 100644 --- a/src/BootstrapBlazor/Components/Tab/Tab.razor +++ b/src/BootstrapBlazor/Components/Tab/Tab.razor @@ -6,40 +6,9 @@ { @Body } -else if (ShowContextMenu) -{ - - @RenderTab - - @if (BeforeContextMenuTemplate != null) - { - @BeforeContextMenuTemplate(this) - } - - - - - - @if (ShowContextMenuFullScreen) - { - - - } - @if (ContextMenuTemplate != null) - { - @ContextMenuTemplate(this) - } - - -} else { - @RenderTab -} - -@code { - RenderFragment RenderTab => - @
+
@if (TabHeader != null) { TabHeader.Render(RenderTabHeader); @@ -67,16 +36,16 @@ else }
-
; + +} +@code { RenderFragment RenderTabHeader => @
@if (BeforeNavigatorTemplate != null) { - - @BeforeNavigatorTemplate - + @BeforeNavigatorTemplate(this) } @if (ShowNavigatorButtons) { @@ -94,45 +63,7 @@ else @ChildContent - @if (!Items.Any() && !string.IsNullOrEmpty(DefaultUrl)) - { - if (ClickTabToNavigation) - { - Navigator.NavigateTo(DefaultUrl); - } - else - { - AddTabItem(DefaultUrl); - } - } - @if (FirstRender) - { - if (!Items.Any(t => t.IsActive)) - { - Items.FirstOrDefault(i => i.IsDisabled == false)?.SetActive(true); - } - } - @foreach (var item in Items) - { - @if (item.HeaderTemplate != null) - { -
- @item.HeaderTemplate(item) -
- } - else if (item.IsDisabled) - { - @RenderDisabledHeaderItem(item) - } - else - { - @RenderHeaderItem(item) - } - } - @if (IsCard || IsBorderCard) - { -
- } + @RenderTabList()
@if (!IsCard && !IsBorderCard && ShowActiveBar) { @@ -140,65 +71,85 @@ else }
- - @if (ButtonTemplate != null) - { - @ButtonTemplate - } - @if (ShowToolbar) - { -
- @if (ShowRefreshToolbarButton) - { - - } - @if (ShowFullscreenToolbarButton) - { -
- -
- } - @if (ToolbarTemplate != null) - { - @ToolbarTemplate - } -
- } - @if (ShowNavigatorButtons) - { - - } - @if (ShouldShowExtendButtons()) - { - - - } - @if (AfterNavigatorTemplate != null) - { - @AfterNavigatorTemplate - } -
+ @if (ButtonTemplate != null) + { + @ButtonTemplate(this) + } + @if (ShowToolbar) + { +
+ @if (ShowRefreshToolbarButton) + { + + } + @if (ShowFullscreenToolbarButton) + { +
+ +
+ } + @if (ToolbarTemplate != null) + { + @ToolbarTemplate(this) + } +
+ } + @if (ShowNavigatorButtons) + { + + } + @if (ShouldShowExtendButtons()) + { + + + } + @if (AfterNavigatorTemplate != null) + { + @AfterNavigatorTemplate(this) + } ; + + RenderFragment RenderContextMenu => + @ + @if (BeforeContextMenuTemplate != null) + { + @BeforeContextMenuTemplate(this) + } + + + + + + @if (ShowContextMenuFullScreen) + { + + + } + @if (ContextMenuTemplate != null) + { + @ContextMenuTemplate(this) + } + ; RenderFragment RenderTabItem => item => @ diff --git a/src/BootstrapBlazor/Components/Tab/Tab.razor.cs b/src/BootstrapBlazor/Components/Tab/Tab.razor.cs index ce030c1cbbb..d47ba62b02d 100644 --- a/src/BootstrapBlazor/Components/Tab/Tab.razor.cs +++ b/src/BootstrapBlazor/Components/Tab/Tab.razor.cs @@ -228,27 +228,27 @@ public partial class Tab : IHandlerException /// 获得/设置 按钮模板 默认 null ///
[Parameter] - public RenderFragment? ButtonTemplate { get; set; } + public RenderFragment? ButtonTemplate { get; set; } /// /// Gets or sets the template of the toolbar button. Default is null. /// [Parameter] - public RenderFragment? ToolbarTemplate { get; set; } + public RenderFragment? ToolbarTemplate { get; set; } /// /// 获得/设置 标签页前置模板 默认 null /// 在向前移动标签页按钮前 /// [Parameter] - public RenderFragment? BeforeNavigatorTemplate { get; set; } + public RenderFragment? BeforeNavigatorTemplate { get; set; } /// /// 获得/设置 标签页后置模板 默认 null /// 在向后移动标签页按钮前 /// [Parameter] - public RenderFragment? AfterNavigatorTemplate { get; set; } + public RenderFragment? AfterNavigatorTemplate { get; set; } /// /// 获得/设置 上一个标签图标 @@ -580,7 +580,9 @@ protected override async Task OnAfterRenderAsync(bool firstRender) /// /// /// - protected override Task InvokeInitAsync() => InvokeVoidAsync("init", Id, Interop, nameof(DragItemCallback), Layout?.Id); + protected override Task InvokeInitAsync() => InvokeVoidAsync("init", Id, Interop, nameof(DragItemCallback), LayoutId); + + private string? LayoutId => Layout is { ShowTabInHeader: true } ? Layout.Id : null; private void RemoveLocationChanged() { @@ -1132,6 +1134,80 @@ private async Task OnContextMenu(MouseEventArgs e, TabItem item) } } + private RenderFragment RenderTabList() => builder => + { + if (!Items.Any() && !string.IsNullOrEmpty(DefaultUrl)) + { + if (ClickTabToNavigation) + { + Navigator.NavigateTo(DefaultUrl); + } + else + { + AddTabItem(DefaultUrl); + } + } + + if (FirstRender) + { + if (!Items.Any(t => t.IsActive)) + { + Items.FirstOrDefault(i => i.IsDisabled == false)?.SetActive(true); + } + } + + if (ShowContextMenu) + { + builder.OpenComponent(0); + builder.AddAttribute(10, nameof(ContextMenuZone.ChildContent), RenderContextMenuZoneContent()); + builder.AddComponentReferenceCapture(20, instance => _contextMenuZone = (ContextMenuZone)instance); + builder.CloseComponent(); + } + else + { + builder.AddContent(150, RenderTabItems()); + } + + if (TabStyle == TabStyle.Default && (IsCard || IsBorderCard)) + { + builder.OpenElement(200, "div"); + builder.AddAttribute(210, "class", "tabs-item-fix"); + builder.CloseElement(); + } + }; + + private RenderFragment RenderContextMenuZoneContent() => builder => + { + builder.AddContent(0, RenderTabItems()); + builder.AddContent(10, RenderContextMenu); + }; + + private RenderFragment RenderTabItems() => builder => + { + for (var index = 0; index < _items.Count; index++) + { + var item = _items[index]; + var sequence = (index + 1) * 100; + if (item.HeaderTemplate != null) + { + builder.OpenElement(sequence, "div"); + builder.SetKey(item); + builder.AddAttribute(sequence + 10, "class", GetItemWrapClassString(item)); + builder.AddAttribute(sequence + 20, "draggable", DraggableString); + builder.AddContent(sequence + 30, item.HeaderTemplate(item)); + builder.CloseElement(); + } + else if (item.IsDisabled) + { + builder.AddContent(sequence + 40, RenderDisabledHeaderItem(item)); + } + else + { + builder.AddContent(sequence + 50, RenderHeaderItem(item)); + } + } + }; + /// /// /// diff --git a/src/BootstrapBlazor/Components/Tab/Tab.razor.scss b/src/BootstrapBlazor/Components/Tab/Tab.razor.scss index 4747744c25c..141d1142cae 100644 --- a/src/BootstrapBlazor/Components/Tab/Tab.razor.scss +++ b/src/BootstrapBlazor/Components/Tab/Tab.razor.scss @@ -82,6 +82,11 @@ position: relative; display: flex; height: 100%; + + .bb-cm-zone { + display: flex; + flex-wrap: nowrap; + } } .tabs-nav-wrap { @@ -501,10 +506,6 @@ --bb-tabs-item-text-padding: 0 .5rem; background-color: var(--bb-tabs-header-bg-color); - .tabs-item-fix { - border: none; - } - .tabs-item-wrap { &:not(.active) { .tabs-item:not(.disabled) .tabs-item-body { @@ -557,6 +558,7 @@ display: flex; align-items: center; border-radius: var(--bs-border-radius); + user-select: none; &:hover { background-color: var(--bb-tabs-item-hover-bg-color); diff --git a/test/UnitTest/Components/LayoutTest.cs b/test/UnitTest/Components/LayoutTest.cs index 16e98a8cd76..2c6e4e9a3b4 100644 --- a/test/UnitTest/Components/LayoutTest.cs +++ b/test/UnitTest/Components/LayoutTest.cs @@ -45,7 +45,7 @@ public async Task TabStyle_Ok() cut.SetParametersAndRender(pb => pb.Add(a => a.ShowFullscreenToolbarButton, false)); Assert.DoesNotContain("tabs-nav-toolbar-fs", cut.Markup); - cut.SetParametersAndRender(pb => pb.Add(a => a.ToolbarTemplate, builder => builder.AddContent(0, "test-toolbar-template"))); + cut.SetParametersAndRender(pb => pb.Add(a => a.ToolbarTemplate, tab => builder => builder.AddContent(0, "test-toolbar-template"))); Assert.Contains("test-toolbar-template", cut.Markup); cut.SetParametersAndRender(pb => pb.Add(a => a.ShowTabContextMenu, true)); diff --git a/test/UnitTest/Components/TabTest.cs b/test/UnitTest/Components/TabTest.cs index 3602fd93a3b..710ec6846b5 100644 --- a/test/UnitTest/Components/TabTest.cs +++ b/test/UnitTest/Components/TabTest.cs @@ -66,7 +66,7 @@ public void ToolbarTemplate_Ok() pb.Add(a => a.Icon, "fa-solid fa-font-awesome"); pb.Add(a => a.ChildContent, "Tab1-Content"); }); - pb.Add(a => a.ToolbarTemplate, builder => builder.AddContent(0, "test-toolbar-template")); + pb.Add(a => a.ToolbarTemplate, tab => builder => builder.AddContent(0, "test-toolbar-template")); }); cut.DoesNotContain("test-toolbar-template"); @@ -765,10 +765,10 @@ public void ButtonTemplate_Ok() var cut = Context.RenderComponent(pb => { pb.Add(a => a.ShowExtendButtons, true); - pb.Add(a => a.ButtonTemplate, new RenderFragment(builder => + pb.Add(a => a.ButtonTemplate, tab => builder => { builder.AddContent(0, new MarkupString("
test-button
")); - })); + }); }); cut.Contains("
test-button
"); } @@ -1034,8 +1034,8 @@ public void BeforeNavigatorTemplate_Ok() { pb.AddChildContent(pb => { - pb.Add(a => a.BeforeNavigatorTemplate, builder => builder.AddContent(0, "before-navigator-template")); - pb.Add(a => a.AfterNavigatorTemplate, builder => builder.AddContent(0, "after-navigator-template")); + pb.Add(a => a.BeforeNavigatorTemplate, tab => builder => builder.AddContent(0, "before-navigator-template")); + pb.Add(a => a.AfterNavigatorTemplate, tab => builder => builder.AddContent(0, "after-navigator-template")); pb.AddChildContent(pb => { pb.Add(a => a.ShowFullScreen, true);