diff --git a/src/BootstrapBlazor.Server/Components/Samples/Splits.razor b/src/BootstrapBlazor.Server/Components/Samples/Splits.razor index 1e434e72981..dc5ea97834b 100644 --- a/src/BootstrapBlazor.Server/Components/Samples/Splits.razor +++ b/src/BootstrapBlazor.Server/Components/Samples/Splits.razor @@ -3,73 +3,93 @@

@Localizer["SplitsTitle"]

-
- -
- - -
-
- -
@Localizer["SplitsPanel2"]
-
-
-
-
+ +
+ + +
@Localizer["SplitsPanel1"]
+
+ +
@Localizer["SplitsPanel2"]
+
+
+
+
- -
- - -
@Localizer["SplitsPanel1"]
-
- -
@Localizer["SplitsPanel2"]
-
-
-
-
+ +
+ + +
@Localizer["SplitsPanel1"]
+
+ +
@Localizer["SplitsPanel2"]
+
+
+
+
- -
- - -
@Localizer["SplitsPanel3"]
-
- -
@Localizer["SplitsPanel4"]
-
-
-
-
+ +
+ + +
@Localizer["SplitsPanel3"]
+
+ +
@Localizer["SplitsPanel4"]
+
+
+
+
- -
- - - - -
@Localizer["SplitsPanel5"]
-
- -
@Localizer["SplitsPanel6"]
-
-
-
- -
@Localizer["SplitsPanel7"]
-
-
-
-
-
+ +
+ + + + +
@Localizer["SplitsPanel5"]
+
+ +
@Localizer["SplitsPanel6"]
+
+
+
+ +
@Localizer["SplitsPanel7"]
+
+
+
+
+ + +
+ + + + +
@Localizer["SplitsPanel8"]
+
+ +
@Localizer["SplitsPanel9"]
+
+
+
+ +
@Localizer["SplitsPanel10"]
+
+
+
+
diff --git a/src/BootstrapBlazor.Server/Components/Samples/Splits.razor.cs b/src/BootstrapBlazor.Server/Components/Samples/Splits.razor.cs index e1fccbf0915..dd73b050534 100644 --- a/src/BootstrapBlazor.Server/Components/Samples/Splits.razor.cs +++ b/src/BootstrapBlazor.Server/Components/Samples/Splits.razor.cs @@ -46,6 +46,14 @@ private AttributeItem[] GetAttributes() => Type = "RenderFragment", ValueList = " — ", DefaultValue = " — " + }, + new() + { + Name = "IsCollapsible", + Description = Localizer["SplitsIsCollapsible"], + Type = "bool", + ValueList = "true|false", + DefaultValue = "false" } ]; } diff --git a/src/BootstrapBlazor.Server/Components/Samples/Splits.razor.css b/src/BootstrapBlazor.Server/Components/Samples/Splits.razor.css index 738336de126..0496142e57e 100644 --- a/src/BootstrapBlazor.Server/Components/Samples/Splits.razor.css +++ b/src/BootstrapBlazor.Server/Components/Samples/Splits.razor.css @@ -1,4 +1,4 @@ -::deep.split-demo { +split-demo { height: 200px; width: 240px; border-color: rgba(0,0,0,.125); @@ -10,12 +10,12 @@ } @media (min-width: 568px) { - ::deep .split-demo { + .split-demo { height: 200px; width: 480px; } - ::deep.split-demo-horizontal { + split-demo-horizontal { height: 100px; } } diff --git a/src/BootstrapBlazor.Server/Locales/en-US.json b/src/BootstrapBlazor.Server/Locales/en-US.json index 7e0032bb70d..339320de87a 100644 --- a/src/BootstrapBlazor.Server/Locales/en-US.json +++ b/src/BootstrapBlazor.Server/Locales/en-US.json @@ -1761,10 +1761,16 @@ "SplitsPanel5": "Upper", "SplitsPanel6": "Lower", "SplitsPanel7": "Right", - "SplitsIsVertical": "style", + "SplitsCollapsibleTitle": "Collapse/Expand", + "SplitsCollapsibleIntro": "Set whether the panels can be collapsed by configuring the FirstPaneCollapsible and SecondPaneCollapsible properties", + "SplitsPanel8": "Upper", + "SplitsPanel9": "Lower", + "SplitsPanel10": "Right", + "SplitsIsVertical": "Vertical", "SplitsBasis": "Percentage of first pane position", "SplitsFirstPanelTemplate": "First pane template", - "SplitsSecondPanelTemplate": "Second pane template" + "SplitsSecondPanelTemplate": "Second pane template", + "SplitsIsCollapsible": "Whether to expand or collapse the split view" }, "BootstrapBlazor.Server.Components.Samples.Dropdowns": { "Title": "Dropdown", diff --git a/src/BootstrapBlazor.Server/Locales/zh-CN.json b/src/BootstrapBlazor.Server/Locales/zh-CN.json index 318efd2028e..d7bacb2dc2e 100644 --- a/src/BootstrapBlazor.Server/Locales/zh-CN.json +++ b/src/BootstrapBlazor.Server/Locales/zh-CN.json @@ -1761,10 +1761,16 @@ "SplitsPanel5": "上边面板", "SplitsPanel6": "下边面板", "SplitsPanel7": "右边面板", - "SplitsIsVertical": "样式", + "SplitsCollapsibleTitle": "折叠/展开", + "SplitsCollapsibleIntro": "通过设置 IsCollapsible 属性来设置是否可以折叠面板", + "SplitsPanel8": "上边面板", + "SplitsPanel9": "下边面板", + "SplitsPanel10": "右边面板", + "SplitsIsVertical": "垂直分割", "SplitsBasis": "第一个窗格位置占比", "SplitsFirstPanelTemplate": "第一个窗格模板", - "SplitsSecondPanelTemplate": "第二个窗格模板" + "SplitsSecondPanelTemplate": "第二个窗格模板", + "SplitsIsCollapsible": "是否可以展开收起面板" }, "BootstrapBlazor.Server.Components.Samples.Dropdowns": { "Title": "Dropdown 下拉菜单", diff --git a/src/BootstrapBlazor/BootstrapBlazor.csproj b/src/BootstrapBlazor/BootstrapBlazor.csproj index e427231b17c..aca71eaa0e3 100644 --- a/src/BootstrapBlazor/BootstrapBlazor.csproj +++ b/src/BootstrapBlazor/BootstrapBlazor.csproj @@ -1,7 +1,7 @@ - 8.8.5-beta02 + 8.8.5-beta03 diff --git a/src/BootstrapBlazor/Components/Split/Split.razor b/src/BootstrapBlazor/Components/Split/Split.razor index 4e8e8193d45..6301b4470e6 100644 --- a/src/BootstrapBlazor/Components/Split/Split.razor +++ b/src/BootstrapBlazor/Components/Split/Split.razor @@ -1,26 +1,26 @@ @namespace BootstrapBlazor.Components @inherits BootstrapModuleComponentBase -@attribute [BootstrapModuleAutoLoader] +@attribute [BootstrapModuleAutoLoader(JSObjectReference = true)]
-
-
- @FirstPaneTemplate -
-
-
- - - - - - - - -
-
-
- @SecondPaneTemplate +
+ @FirstPaneTemplate +
+
+ @SecondPaneTemplate +
+
+ @if (IsCollapsible) + { + + } +
+
+
+ @if (IsCollapsible) + { + + }
diff --git a/src/BootstrapBlazor/Components/Split/Split.razor.cs b/src/BootstrapBlazor/Components/Split/Split.razor.cs index 0b5b06c50ee..1c31dce9201 100644 --- a/src/BootstrapBlazor/Components/Split/Split.razor.cs +++ b/src/BootstrapBlazor/Components/Split/Split.razor.cs @@ -5,7 +5,7 @@ namespace BootstrapBlazor.Components; /// -/// +/// Split 组件 /// public sealed partial class Split { @@ -13,16 +13,10 @@ public sealed partial class Split /// 获得 组件样式 /// private string? ClassString => CssBuilder.Default("split") + .AddClass("is-vertical", IsVertical) .AddClassFromAttributes(AdditionalAttributes) .Build(); - /// - /// 获得 组件 Wrapper 样式 - /// - private string? WrapperClassString => CssBuilder.Default("split-wrapper") - .AddClass("is-horizontal", !IsVertical) - .Build(); - /// /// 获得 第一个窗格 Style /// @@ -30,6 +24,12 @@ public sealed partial class Split .AddClass($"flex-basis: {Basis.ConvertToPercentString()};") .Build(); + /// + /// 获取 是否开启折叠功能 默认 false + /// + [Parameter] + public bool IsCollapsible { get; set; } + /// /// 获得/设置 是否垂直分割 /// @@ -53,4 +53,30 @@ public sealed partial class Split /// [Parameter] public RenderFragment? SecondPaneTemplate { get; set; } + + /// + /// 获得/设置 窗格折叠时回调方法 参数 bool 值为 true 是表示已折叠 值为 false 表示第二个已折叠 + /// + [Parameter] + public Func? OnCollapsedAsync { get; set; } + + /// + /// + /// + /// + protected override Task InvokeInitAsync() => InvokeVoidAsync("init", Id, Interop, nameof(TriggerOnCollapsed)); + + /// + /// 窗格折叠时回调方法 由 JavaScript 调用 + /// + /// + /// + [JSInvokable] + public async Task TriggerOnCollapsed(bool collapsed) + { + if (OnCollapsedAsync != null) + { + await OnCollapsedAsync(collapsed); + } + } } diff --git a/src/BootstrapBlazor/Components/Split/Split.razor.js b/src/BootstrapBlazor/Components/Split/Split.razor.js index 392aed0bfa7..227337d3bbd 100644 --- a/src/BootstrapBlazor/Components/Split/Split.razor.js +++ b/src/BootstrapBlazor/Components/Split/Split.razor.js @@ -1,9 +1,8 @@ -import { getHeight, getInnerHeight } from "../../modules/utility.js" -import Data from "../../modules/data.js" +import Data from "../../modules/data.js" import Drag from "../../modules/drag.js" import EventHandler from "../../modules/event-handler.js" -export function init(id) { +export function init(id, invoke, method) { const el = document.getElementById(id) if (el === null) { return @@ -17,11 +16,10 @@ export function init(id) { let newVal = 0 let originX = 0 let originY = 0 - const splitWrapper = el.firstElementChild - const isVertical = !splitWrapper.classList.contains('is-horizontal') - const splitBar = splitWrapper.children[1] - const splitLeft = splitWrapper.children[0] - const splitRight = splitWrapper.children[2]; + const isVertical = el.classList.contains('is-vertical') + const splitLeft = el.children[0]; + const splitRight = el.children[1]; + const splitBar = el.children[2]; split.splitBar = splitBar; Drag.drag(splitBar, @@ -58,7 +56,35 @@ export function init(id) { () => { el.classList.remove('dragging'); removeMask(splitLeft, splitRight); - }) + } + ); + + let start = 0; + const step = ts => { + if (start === 0) { + start = ts; + } + if (ts - start > 300) { + splitLeft.classList.remove('is-collapsed'); + } + requestAnimationFrame(step); + } + + EventHandler.on(splitBar, 'click', '.split-bar-arrow', e => { + var element = e.delegateTarget; + splitLeft.classList.add('is-collapsed'); + if (element.classList.contains("split-bar-arrow-left")) { + splitLeft.style.setProperty('flex-basis', '0%'); + invoke.invokeMethodAsync(method, true); + } + else { + splitLeft.style.setProperty('flex-basis', '100%'); + invoke.invokeMethodAsync(method, false); + } + splitRight.style.removeProperty('flex-basis'); + start = 0; + requestAnimationFrame(step); + }); } const showMask = (left, right) => { @@ -89,6 +115,9 @@ export function dispose(id) { if (split) { const { el } = split; - Drag.dispose(el) + if (el.splitBar) { + EventHandler.off(splitBar, 'click', '.split-bar-arrow'); + Drag.dispose(el.splitBar); + } } } diff --git a/src/BootstrapBlazor/Components/Split/Split.razor.scss b/src/BootstrapBlazor/Components/Split/Split.razor.scss index 4c477069dff..c3242fe4919 100644 --- a/src/BootstrapBlazor/Components/Split/Split.razor.scss +++ b/src/BootstrapBlazor/Components/Split/Split.razor.scss @@ -1,83 +1,297 @@ +[data-bs-theme='dark'] .split { + --bb-split-bar-bg: #{$bb-split-bar-bg-dark}; + --bb-split-bar-handle-bg: #{$bb-split-bar-handle-bg-dark}; + --bb-split-bar-handle-color: #{$bb-split-bar-handle-color-dark}; + --bb-split-bar-handle-hover-bg: #{$bb-split-bar-handle-hover-bg-dark}; + --bb-split-bar-handle-hover-color: #{$bb-split-bar-handle-hover-color-dark}; + --bb-split-bar-arrow-hover-border-color: #{$bb-split-bar-arrow-hover-border-color-dark}; +} + .split { - --bb-split-bar-height: #{$bb-split-bar-height}; - --bb-split-bar-hover-bg: #{$bb-split-bar-hover-bg}; - display: block; + --bb-split-bar-bg: #{$bb-split-bar-bg}; + --bb-split-bar-hover-bg: var(--bb-primary-color); + --bb-split-bar-width: #{$bb-split-bar-width}; + --bb-split-bar-handle-bg: #{$bb-split-bar-handle-bg}; + --bb-split-bar-handle-color: #{$bb-split-bar-handle-color}; + --bb-split-bar-handle-hover-bg: #{$bb-split-bar-handle-hover-bg}; + --bb-split-bar-handle-hover-color: #{$bb-split-bar-handle-hover-color}; + --bb-split-bar-arrow-bg: #{$bb-split-bar-arrow-bg}; + --bb-split-bar-arrow-border-color: #{$bb-split-bar-arrow-border-color}; + --bb-split-bar-arrow-hover-bg: #{$bb-split-bar-arrow-hover-bg}; + --bb-split-bar-arrow-hover-border-color: #{$bb-split-bar-arrow-hover-border-color}; height: 100%; width: 100%; + display: flex; + flex-direction: row; + overflow: hidden; - .split-wrapper { - display: flex; + &.is-vertical { flex-direction: column; - height: 100%; - } - .split-wrapper.is-horizontal { - flex-direction: row; - } + .split-bar { + cursor: row-resize; + width: auto; + height: var(--bb-split-bar-width); - &.dragging .split-wrapper { - cursor: row-resize; - } + &:after { + content: ""; + cursor: row-resize; + display: block; + height: 16px; + position: absolute; + width: 100%; + z-index: 12; + } - &.dragging .split-wrapper.is-horizontal { - cursor: col-resize; + &:hover { + .split-bar-arrow-left { + &:before { + transform: rotate(125deg); + } + + &:after { + transform: rotate(50deg); + } + } + + .split-bar-arrow-right { + &:before { + transform: rotate(55deg); + transform-origin: 1px 6px 0; + } + + &:after { + transform: rotate(125deg); + transform-origin: 1px 2px 0; + } + } + } + + .split-bar-arrow { + width: 26px; + + &:before, &:after { + content: ""; + border-radius: 16px; + height: 8px; + transform: rotate(90deg); + width: 2px; + } + } + + .split-bar-arrow-left { + left: 24px; + bottom: 20px; + + &:before { + top: 3px; + left: 10px; + transform-origin: 2px 7px 0; + } + + &:after { + left: 11px; + top: 8px; + transform-origin: 1px 1px 0; + } + } + + .split-bar-arrow-right { + left: -25px; + top: 20px; + + &:before { + left: 12px; + top: 8px; + transform-origin: 1px 6px 0; + } + + &:after { + left: 10px; + top: 12px; + transform-origin: 1px 2px 0; + } + } + + .split-bar-handler { + width: 24px; + padding: 0 2px; + flex-direction: column; + + > div { + width: 100%; + height: 2px; + + &:not(:first-child) { + margin-left: 0; + margin-top: 4px; + } + } + } + } } .split-pane { + width: 100%; height: 100%; - overflow: hidden; position: relative; } + .split-left { + order: 0; + overflow: hidden; + + &.is-collapsed { + transition: flex-basis .3s linear; + } + } + + .split-right { + order: 2; + flex: 1; + overflow: hidden; + } + .split-bar { + order: 1; + width: var(--bb-split-bar-width); display: flex; justify-content: center; align-items: center; - height: var(--bb-split-bar-height); - width: 100%; - border: 1px solid var(--bs-border-color); - border-left: none; - border-right: none; - cursor: row-resize; - overflow: unset; - } + cursor: col-resize; + background-color: var(--bb-split-bar-bg); + z-index: 10; + transition: background-color .3s linear; - .split-bar:hover, - &.dragging > .split-wrapper > .split-bar { - background-color: var(--bb-split-bar-hover-bg); - } + &:after { + content: ""; + cursor: col-resize; + display: block; + height: 100%; + position: absolute; + width: 16px; + z-index: 10; + } - .split-bar:hover .split-trigger-bar, - &.dragging > .split-wrapper > .split-bar .split-trigger-bar { - background-color: var(--bs-body-bg); - } + &:hover { + background: var(--bb-split-bar-hover-bg); - .split-trigger { - font-size: 0; - display: inline-block; - } + .split-bar-handler { + background-color: var(--bb-split-bar-handle-hover-bg); - .split-bar .split-trigger-bar { - width: 1px; - height: 4px; - background: rgba(var(--bs-body-color-rgb), .25); - margin-left: 3px; - display: inline-block; - } + > div { + background: var(--bb-split-bar-handle-hover-color); + } + } - .split-wrapper.is-horizontal > .split-bar { - width: 6px; - height: 100%; - border: 1px solid var(--bs-border-color); - border-top: none; - border-bottom: none; - cursor: col-resize; + .split-bar-arrow { + background-color: var(--bb-split-bar-arrow-hover-bg); + border-color: var(--bb-split-bar-arrow-hover-border-color); + border-width: 1px; + + &:before, + &:after { + background-color: var(--bb-split-bar-arrow-hover-border-color); + opacity: 1; + } + } + + .split-bar-arrow-left { + &:before { + transform: rotate(45deg); + } + + &:after { + transform: rotate(-45deg); + } + } + + .split-bar-arrow-right { + &:before { + transform: rotate(-40deg); + } + + &:after { + transform: rotate(40deg); + } + } + } + + .split-bar-arrow { + background-color: var(--bb-split-bar-arrow-bg); + border-color: var(--bb-split-bar-arrow-border-color); + transition: background-color 500ms ease-out; + border-radius: 50%; + border-image: none; + border-width: 1px; + cursor: pointer; + display: flex; + height: 26px; + padding: 1px 12px; + position: relative; + opacity: 0.9; + z-index: 5; + + &:before, + &:after { + content: ""; + background-color: var(--bb-split-bar-arrow-bg); + opacity: 0; + transition-duration: .3s; + transition-timing-function: cubic-bezier(0.25, 0.1, 0.25, 1); + border-radius: 16px; + height: 8px; + position: absolute; + transform: rotate(0deg); + width: 2px; + } + + &:before { + top: 5px; + transform-origin: 1px 7px 0; + } + + &:after { + top: 11px; + transform-origin: 1px 1px 0; + } + } + + .split-bar-handler { + display: flex; + justify-content: center; + align-items: center; + height: 24px; + position: relative; + background-color: var(--bb-split-bar-handle-bg); + padding: 2px 0px; + + > div { + border-radius: 3px; + background: var(--bb-split-bar-handle-color); + width: 2px; + height: 100%; + + &:not(:first-child) { + margin-left: 4px; + } + } + } + + .split-bar-arrow-left { + right: 5px; + + &:before, &:after { + left: 8px; + } + } + + .split-bar-arrow-right { + left: 5px; - .split-trigger-bar { - width: 4px; - height: 1px; - margin-left: 0; - margin-top: 3px; + &:before, &:after { + right: 8px; + } } } } diff --git a/src/BootstrapBlazor/wwwroot/scss/bootstrapblazor-dark.scss b/src/BootstrapBlazor/wwwroot/scss/bootstrapblazor-dark.scss index 78b1e8b24ef..b409602f460 100644 --- a/src/BootstrapBlazor/wwwroot/scss/bootstrapblazor-dark.scss +++ b/src/BootstrapBlazor/wwwroot/scss/bootstrapblazor-dark.scss @@ -1,2 +1,10 @@ // Dial-Button $bb-dial-item-hover-bg-dark: #313131; + +// Split +$bb-split-bar-bg-dark: #495057; +$bb-split-bar-handle-bg-dark: var(--bs-body-bg); +$bb-split-bar-handle-color-dark: #999; +$bb-split-bar-handle-hover-bg-dark: var(--bs-body-bg); +$bb-split-bar-handle-hover-color-dark: #999; +$bb-split-bar-arrow-hover-border-color-dark: #686a6c; diff --git a/src/BootstrapBlazor/wwwroot/scss/theme/bootstrapblazor.scss b/src/BootstrapBlazor/wwwroot/scss/theme/bootstrapblazor.scss index c587267a3a4..b375377a447 100644 --- a/src/BootstrapBlazor/wwwroot/scss/theme/bootstrapblazor.scss +++ b/src/BootstrapBlazor/wwwroot/scss/theme/bootstrapblazor.scss @@ -542,8 +542,16 @@ $bb-spinner-border-width-xxl: 6rem; $bb-spinner-border-border-width-xxl: .275em; // Split -$bb-split-bar-height: 6px; -$bb-split-bar-hover-bg: #409eff; +$bb-split-bar-bg: #dee2e6; +$bb-split-bar-width: 3px; +$bb-split-bar-handle-bg: #fff; +$bb-split-bar-handle-color: #606266; +$bb-split-bar-handle-hover-bg: #fff; +$bb-split-bar-handle-hover-color: #606266; +$bb-split-bar-arrow-bg: rgba(0, 0, 0, 0); +$bb-split-bar-arrow-border-color: rgba(0, 0, 0, 0); +$bb-split-bar-arrow-hover-bg: rgba(0, 0, 0, 0); +$bb-split-bar-arrow-hover-border-color: #0d6efd; // Step $bb-step-border-width: 2px; diff --git a/test/UnitTest/Components/SplitTest.cs b/test/UnitTest/Components/SplitTest.cs index 5db39b1dc6b..103df2438fd 100644 --- a/test/UnitTest/Components/SplitTest.cs +++ b/test/UnitTest/Components/SplitTest.cs @@ -11,13 +11,13 @@ public void SplitStyle_Ok() { var cut = Context.RenderComponent(pb => { - pb.Add(b => b.FirstPaneTemplate, BuildeComponent("I am Pane1")); - pb.Add(b => b.SecondPaneTemplate, BuildeComponent("I am Pane2")); + pb.Add(b => b.FirstPaneTemplate, RenderSplitView("I am Pane1")); + pb.Add(b => b.SecondPaneTemplate, RenderSplitView("I am Pane2")); pb.Add(b => b.IsVertical, true); }); Assert.Contains("I am Pane1", cut.Markup); Assert.Contains("I am Pane2", cut.Markup); - Assert.DoesNotContain("is-horizontal", cut.Markup); + Assert.Contains("is-vertical", cut.Markup); cut.SetParametersAndRender(pb => { @@ -27,15 +27,55 @@ public void SplitStyle_Ok() cut.SetParametersAndRender(pb => { - pb.Add(b => b.AdditionalAttributes, new Dictionary() { ["tag"] = "tagok" }); + pb.Add(b => b.AdditionalAttributes, new Dictionary() { ["tag"] = "tag" }); }); - Assert.Contains("tagok", cut.Markup); + Assert.Contains("tag", cut.Markup); + } + + [Fact] + public void IsCollapsible_Ok() + { + var cut = Context.RenderComponent(pb => + { + pb.Add(b => b.FirstPaneTemplate, RenderSplitView("I am Pane1")); + pb.Add(b => b.SecondPaneTemplate, RenderSplitView("I am Pane2")); + }); + cut.DoesNotContain("split-bar-arrow-left"); + cut.DoesNotContain("split-bar-arrow-right"); + + cut.SetParametersAndRender(pb => + { + pb.Add(b => b.IsCollapsible, true); + }); + cut.Contains("split-bar-arrow-left"); + cut.Contains("split-bar-arrow-right"); + } - RenderFragment BuildeComponent(string name = "I am Pane1") => builder => + [Fact] + public async Task OnCollapsedAsync_Ok() + { + var state = false; + var cut = Context.RenderComponent(pb => { - builder.OpenElement(1, "div"); - builder.AddContent(2, name); - builder.CloseElement(); - }; + pb.Add(b => b.FirstPaneTemplate, RenderSplitView("I am Pane1")); + pb.Add(b => b.SecondPaneTemplate, RenderSplitView("I am Pane2")); + pb.Add(b => b.IsCollapsible, true); + pb.Add(b => b.OnCollapsedAsync, async (collapsed) => + { + state = collapsed; + await Task.CompletedTask; + }); + }); + await cut.InvokeAsync(() => cut.Instance.TriggerOnCollapsed(true)); + Assert.True(state); + await cut.InvokeAsync(() => cut.Instance.TriggerOnCollapsed(false)); + Assert.False(state); } + + static RenderFragment RenderSplitView(string name = "I am Pane1") => builder => + { + builder.OpenElement(1, "div"); + builder.AddContent(2, name); + builder.CloseElement(); + }; }