Skip to content

Commit

Permalink
feat(split): support pane collapsible (#4138)
Browse files Browse the repository at this point in the history
* feat(split): support pane collapsible

* modify css

* modify css

* beautify and fix bugs

* adjust parameter

* modify unit tests

* modify unit tests

* coverage

* modify css

* fix bugs

* wip: test modify PR

* add document

* fix bugs

* modify some description

* fix bugs

* refactor: 调整 bar 样式

* style: 调整垂直样式

* style: 增加垂直布局样式

* style: 增加 handler 样式

* style: 更新垂直布局样式

* refactor: 增加 IsCollapsible 参数

* refactor: 增加按钮支持

* style: 微调样式

* doc: 精简 dom 结构

* style: 微调样式适配收起动画

* feat: 更新脚本实现收起展开动画特效

* style: 颜色变量化

* style: 增加动画效果

* doc: 更新文档说明

* test: 更新单元测试

* feat: 增加 OnCollapsedAsync 回调方法

* feat: 实现 OnCollapsedAsync 逻辑

* test: 增加单元测试

* doc: 移除不需要的本地化设置

* chore: bump version 8.8.5-beta03

* style: 增加暗黑主题颜色

* style: 更正暗黑主题变量

---------

Co-authored-by: Argo Zhang <argo@live.ca>
  • Loading branch information
izanhzh and ArgoZhang authored Aug 27, 2024
1 parent c66b9f2 commit 25a413c
Show file tree
Hide file tree
Showing 13 changed files with 542 additions and 177 deletions.
150 changes: 85 additions & 65 deletions src/BootstrapBlazor.Server/Components/Samples/Splits.razor
Original file line number Diff line number Diff line change
Expand Up @@ -3,73 +3,93 @@

<h3>@Localizer["SplitsTitle"]</h3>

<div>
<DemoBlock Title="@Localizer["SplitsNormalTitle"]"
Introduction="@Localizer["SplitsNormalIntro"]"
Name="Normal">
<div class="border split-demo split-demo-horizontal">
<Split>
<FirstPaneTemplate>
<div class="d-flex justify-content-center align-items-center h-100"></div>
</FirstPaneTemplate>
<SecondPaneTemplate>
<div class="d-flex justify-content-center align-items-center h-100">@Localizer["SplitsPanel2"]</div>
</SecondPaneTemplate>
</Split>
</div>
</DemoBlock>
<DemoBlock Title="@Localizer["SplitsNormalTitle"]"
Introduction="@Localizer["SplitsNormalIntro"]"
Name="Normal">
<div class="border split-demo split-demo-horizontal">
<Split>
<FirstPaneTemplate>
<div class="d-flex justify-content-center align-items-center h-100">@Localizer["SplitsPanel1"]</div>
</FirstPaneTemplate>
<SecondPaneTemplate>
<div class="d-flex justify-content-center align-items-center h-100">@Localizer["SplitsPanel2"]</div>
</SecondPaneTemplate>
</Split>
</div>
</DemoBlock>

<DemoBlock Title="@Localizer["SplitsPercentTitle"]"
Introduction="@Localizer["SplitsPercentIntro"]"
Name="Basis">
<div class="border split-demo split-demo-horizontal">
<Split Basis="40%">
<FirstPaneTemplate>
<div class="d-flex justify-content-center align-items-center h-100">@Localizer["SplitsPanel1"]</div>
</FirstPaneTemplate>
<SecondPaneTemplate>
<div class="d-flex justify-content-center align-items-center h-100">@Localizer["SplitsPanel2"]</div>
</SecondPaneTemplate>
</Split>
</div>
</DemoBlock>
<DemoBlock Title="@Localizer["SplitsPercentTitle"]"
Introduction="@Localizer["SplitsPercentIntro"]"
Name="Basis">
<div class="border split-demo split-demo-horizontal">
<Split Basis="40%">
<FirstPaneTemplate>
<div class="d-flex justify-content-center align-items-center h-100">@Localizer["SplitsPanel1"]</div>
</FirstPaneTemplate>
<SecondPaneTemplate>
<div class="d-flex justify-content-center align-items-center h-100">@Localizer["SplitsPanel2"]</div>
</SecondPaneTemplate>
</Split>
</div>
</DemoBlock>

<DemoBlock Title="@Localizer["SplitsVerticalTitle"]"
Introduction="@Localizer["SplitsVerticalIntro"]"
Name="IsVertical">
<div class="border split-demo">
<Split IsVertical="true">
<FirstPaneTemplate>
<div class="d-flex justify-content-center align-items-center h-100">@Localizer["SplitsPanel3"]</div>
</FirstPaneTemplate>
<SecondPaneTemplate>
<div class="d-flex justify-content-center align-items-center h-100">@Localizer["SplitsPanel4"]</div>
</SecondPaneTemplate>
</Split>
</div>
</DemoBlock>
<DemoBlock Title="@Localizer["SplitsVerticalTitle"]"
Introduction="@Localizer["SplitsVerticalIntro"]"
Name="IsVertical">
<div class="border split-demo">
<Split IsVertical="true">
<FirstPaneTemplate>
<div class="d-flex justify-content-center align-items-center h-100">@Localizer["SplitsPanel3"]</div>
</FirstPaneTemplate>
<SecondPaneTemplate>
<div class="d-flex justify-content-center align-items-center h-100">@Localizer["SplitsPanel4"]</div>
</SecondPaneTemplate>
</Split>
</div>
</DemoBlock>

<DemoBlock Title="@Localizer["SplitsNestedTitle"]"
Introduction="@Localizer["SplitsNestedIntro"]"
Name="Nested">
<div class="border split-demo">
<Split>
<FirstPaneTemplate>
<Split IsVertical="true">
<FirstPaneTemplate>
<div class="d-flex justify-content-center align-items-center h-100">@Localizer["SplitsPanel5"]</div>
</FirstPaneTemplate>
<SecondPaneTemplate>
<div class="d-flex justify-content-center align-items-center h-100">@Localizer["SplitsPanel6"]</div>
</SecondPaneTemplate>
</Split>
</FirstPaneTemplate>
<SecondPaneTemplate>
<div class="d-flex justify-content-center align-items-center h-100">@Localizer["SplitsPanel7"]</div>
</SecondPaneTemplate>
</Split>
</div>
</DemoBlock>
</div>
<DemoBlock Title="@Localizer["SplitsNestedTitle"]"
Introduction="@Localizer["SplitsNestedIntro"]"
Name="Nested">
<div class="border split-demo">
<Split>
<FirstPaneTemplate>
<Split IsVertical="true">
<FirstPaneTemplate>
<div class="d-flex justify-content-center align-items-center h-100">@Localizer["SplitsPanel5"]</div>
</FirstPaneTemplate>
<SecondPaneTemplate>
<div class="d-flex justify-content-center align-items-center h-100">@Localizer["SplitsPanel6"]</div>
</SecondPaneTemplate>
</Split>
</FirstPaneTemplate>
<SecondPaneTemplate>
<div class="d-flex justify-content-center align-items-center h-100">@Localizer["SplitsPanel7"]</div>
</SecondPaneTemplate>
</Split>
</div>
</DemoBlock>

<DemoBlock Title="@Localizer["SplitsCollapsibleTitle"]"
Introduction="@Localizer["SplitsCollapsibleIntro"]"
Name="Collapsible">
<div class="border split-demo">
<Split IsCollapsible="true">
<FirstPaneTemplate>
<Split IsVertical="true" IsCollapsible="true">
<FirstPaneTemplate>
<div class="d-flex justify-content-center align-items-center h-100">@Localizer["SplitsPanel8"]</div>
</FirstPaneTemplate>
<SecondPaneTemplate>
<div class="d-flex justify-content-center align-items-center h-100">@Localizer["SplitsPanel9"]</div>
</SecondPaneTemplate>
</Split>
</FirstPaneTemplate>
<SecondPaneTemplate>
<div class="d-flex justify-content-center align-items-center h-100">@Localizer["SplitsPanel10"]</div>
</SecondPaneTemplate>
</Split>
</div>
</DemoBlock>

<AttributeTable Items="@GetAttributes()" />
8 changes: 8 additions & 0 deletions src/BootstrapBlazor.Server/Components/Samples/Splits.razor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,14 @@ private AttributeItem[] GetAttributes() =>
Type = "RenderFragment",
ValueList = " — ",
DefaultValue = " — "
},
new()
{
Name = "IsCollapsible",
Description = Localizer["SplitsIsCollapsible"],
Type = "bool",
ValueList = "true|false",
DefaultValue = "false"
}
];
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
::deep.split-demo {
split-demo {
height: 200px;
width: 240px;
border-color: rgba(0,0,0,.125);
Expand All @@ -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;
}
}
10 changes: 8 additions & 2 deletions src/BootstrapBlazor.Server/Locales/en-US.json
Original file line number Diff line number Diff line change
Expand Up @@ -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 <code>FirstPaneCollapsible</code> and <code>SecondPaneCollapsible</code> 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",
Expand Down
10 changes: 8 additions & 2 deletions src/BootstrapBlazor.Server/Locales/zh-CN.json
Original file line number Diff line number Diff line change
Expand Up @@ -1761,10 +1761,16 @@
"SplitsPanel5": "上边面板",
"SplitsPanel6": "下边面板",
"SplitsPanel7": "右边面板",
"SplitsIsVertical": "样式",
"SplitsCollapsibleTitle": "折叠/展开",
"SplitsCollapsibleIntro": "通过设置 <code>IsCollapsible</code> 属性来设置是否可以折叠面板",
"SplitsPanel8": "上边面板",
"SplitsPanel9": "下边面板",
"SplitsPanel10": "右边面板",
"SplitsIsVertical": "垂直分割",
"SplitsBasis": "第一个窗格位置占比",
"SplitsFirstPanelTemplate": "第一个窗格模板",
"SplitsSecondPanelTemplate": "第二个窗格模板"
"SplitsSecondPanelTemplate": "第二个窗格模板",
"SplitsIsCollapsible": "是否可以展开收起面板"
},
"BootstrapBlazor.Server.Components.Samples.Dropdowns": {
"Title": "Dropdown 下拉菜单",
Expand Down
2 changes: 1 addition & 1 deletion src/BootstrapBlazor/BootstrapBlazor.csproj
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk.Razor">

<PropertyGroup>
<Version>8.8.5-beta02</Version>
<Version>8.8.5-beta03</Version>
</PropertyGroup>

<ItemGroup Condition="'$(TargetFramework)' == 'net5.0'">
Expand Down
38 changes: 19 additions & 19 deletions src/BootstrapBlazor/Components/Split/Split.razor
Original file line number Diff line number Diff line change
@@ -1,26 +1,26 @@
@namespace BootstrapBlazor.Components
@inherits BootstrapModuleComponentBase
@attribute [BootstrapModuleAutoLoader]
@attribute [BootstrapModuleAutoLoader(JSObjectReference = true)]

<div @attributes="@AdditionalAttributes" id="@Id" class="@ClassString" role="group">
<div class="@WrapperClassString">
<div class="split-pane split-left" style="@StyleString">
@FirstPaneTemplate
</div>
<div class="split-pane split-bar">
<div class="split-trigger">
<i class="split-trigger-bar"></i>
<i class="split-trigger-bar"></i>
<i class="split-trigger-bar"></i>
<i class="split-trigger-bar"></i>
<i class="split-trigger-bar"></i>
<i class="split-trigger-bar"></i>
<i class="split-trigger-bar"></i>
<i class="split-trigger-bar"></i>
</div>
</div>
<div class="split-pane split-right" style="flex: 1;">
@SecondPaneTemplate
<div class="split-pane split-left" style="@StyleString">
@FirstPaneTemplate
</div>
<div class="split-pane split-right">
@SecondPaneTemplate
</div>
<div class="split-pane split-bar">
@if (IsCollapsible)
{
<button tabindex="-1" type="button" class="split-bar-arrow split-bar-arrow-left"></button>
}
<div class="split-bar-handler">
<div></div>
<div></div>
</div>
@if (IsCollapsible)
{
<button tabindex="-1" type="button" class="split-bar-arrow split-bar-arrow-right"></button>
}
</div>
</div>
42 changes: 34 additions & 8 deletions src/BootstrapBlazor/Components/Split/Split.razor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,31 +5,31 @@
namespace BootstrapBlazor.Components;

/// <summary>
///
/// Split 组件
/// </summary>
public sealed partial class Split
{
/// <summary>
/// 获得 组件样式
/// </summary>
private string? ClassString => CssBuilder.Default("split")
.AddClass("is-vertical", IsVertical)
.AddClassFromAttributes(AdditionalAttributes)
.Build();

/// <summary>
/// 获得 组件 Wrapper 样式
/// </summary>
private string? WrapperClassString => CssBuilder.Default("split-wrapper")
.AddClass("is-horizontal", !IsVertical)
.Build();

/// <summary>
/// 获得 第一个窗格 Style
/// </summary>
private string? StyleString => CssBuilder.Default()
.AddClass($"flex-basis: {Basis.ConvertToPercentString()};")
.Build();

/// <summary>
/// 获取 是否开启折叠功能 默认 false
/// </summary>
[Parameter]
public bool IsCollapsible { get; set; }

/// <summary>
/// 获得/设置 是否垂直分割
/// </summary>
Expand All @@ -53,4 +53,30 @@ public sealed partial class Split
/// </summary>
[Parameter]
public RenderFragment? SecondPaneTemplate { get; set; }

/// <summary>
/// 获得/设置 窗格折叠时回调方法 参数 bool 值为 true 是表示已折叠 值为 false 表示第二个已折叠
/// </summary>
[Parameter]
public Func<bool, Task>? OnCollapsedAsync { get; set; }

/// <summary>
/// <inheritdoc/>
/// </summary>
/// <returns></returns>
protected override Task InvokeInitAsync() => InvokeVoidAsync("init", Id, Interop, nameof(TriggerOnCollapsed));

/// <summary>
/// 窗格折叠时回调方法 由 JavaScript 调用
/// </summary>
/// <param name="collapsed"></param>
/// <returns></returns>
[JSInvokable]
public async Task TriggerOnCollapsed(bool collapsed)
{
if (OnCollapsedAsync != null)
{
await OnCollapsedAsync(collapsed);
}
}
}
Loading

0 comments on commit 25a413c

Please sign in to comment.