mirror of
https://gitee.com/LongbowEnterprise/BootstrapBlazor.git
synced 2024-11-29 18:49:08 +08:00
refactor(Layout): enhance layout styles (#4679)
* doc: 代码格式化 * refactor: 移除空属性 * refactor: 重新设计收起样式 * feat: Layout 组件支持 static 渲染模式 * fix(Widget): 修复报错问题 * chore: bump version 9.0.0-beta03 * style: 移除抽屉 padding 间隙 * refactor: 移除宽度计算样式 * doc: 后台示例更新登录信息栏 * doc: 格式化文档 * refactor: 样式独立文件 * doc: 精简样式 * refactor: 更新 Widget 组件与模板一致 * refactor: 修复调整结构组件状态不正确问题 * refactor: 重构方法提高性能 * refactor: 修复布尔值时不触发 OnStateChanged 回调问题 * refactor: 修复布尔值时不触发 OnStateChanged 回调问题 * test: 增加单元测试 * refactor: 精简代码提高效率 * refactor: 调整右侧边框样式 * chore: bump version 9.0.1-beta01 * doc: 移除 2019 文字 * doc: 移除 2019 文字 * refactor: 更改样式名称 * refactor: 重构侧边栏收起样式 * refactor: 更新 Menu 透明样式 * doc: 更新后台管理样式 * style: 兼容 Menu 组件 * style: 增加响应式布局 * refactor: 重构样式 * wip: 临时移除静态支持 * style: 微调样式 * refactor: 精简样式 * style: 微调 Menu 样式 * refactor: 增加层次 * style: 调整 Title 颜色 * style: 调整收起展开菜单宽度样式 * style: 增加菜单右侧边框线 * doc: 调整文档 * doc: 更新文档链接 * style: 合并样式 * style: 合并样式 * style: 整理 header-bar 样式 * refactor: 重构样式 * style: 层次化样式 * style: 层次化样式 * refactor: 移除 IsPage 参数 * refactor: 移除 static 判断逻辑 * style: 合并 Header 样式 * refactor: 移除侧边栏抽屉 * style: 合并样式 * refactor: 移除 SideWidth=“0” 设置 * refactor: 使用 div 元素渲染按钮 * refactor: 恢复脚本 * refactor: 重构代码 * doc: 移除 IsPage 文档 * doc: 更新开发工具名称
This commit is contained in:
parent
f24b4f47b8
commit
1aacef59b0
@ -1,5 +1,5 @@
|
||||
<DropdownWidget>
|
||||
<DropdownWidgetItem Icon="fa-regular fa-envelope" BadgeNumber="4" BadgeColor="Color.Primary">
|
||||
<DropdownWidget class="px-3 d-none d-sm-block">
|
||||
<DropdownWidgetItem Icon="fa-regular fa-envelope" BadgeNumber="4">
|
||||
<HeaderTemplate>
|
||||
<span>您有 4 个未读消息</span>
|
||||
</HeaderTemplate>
|
||||
@ -8,12 +8,12 @@
|
||||
{
|
||||
<a class="dropdown-item d-flex align-items-center" href="#" @onclick:preventDefault>
|
||||
<div style="width: 40px; height: 40px;">
|
||||
<Avatar Url="./images/Argo-C.png" IsCircle="true" Size="Size.Small" />
|
||||
<Avatar Url="images/Argo-C.png" IsCircle="true" Size="Size.Small" />
|
||||
</div>
|
||||
<div class="ms-2">
|
||||
<div class="d-flex position-relative">
|
||||
<h4>Argo Zhang</h4>
|
||||
<small><i class="fa-regular fa-clock"></i> @(4 + index) mins</small>
|
||||
<div class="flex-fill">Argo Zhang</div>
|
||||
<small><i class="fa fa-clock-o"></i> @(4 + index) mins</small>
|
||||
</div>
|
||||
<div class="text-truncate">Why not buy a new awesome theme?</div>
|
||||
</div>
|
||||
@ -24,7 +24,7 @@
|
||||
<a href="#" @onclick:preventDefault>查看所有消息</a>
|
||||
</FooterTemplate>
|
||||
</DropdownWidgetItem>
|
||||
<DropdownWidgetItem Icon="fa-regular fa-bell" BadgeNumber="10" HeaderColor="Color.Success" BadgeColor="Color.Success">
|
||||
<DropdownWidgetItem Icon="fa-regular fa-bell" BadgeNumber="10" HeaderColor="Color.Success" BadgeColor="Color.Warning">
|
||||
<HeaderTemplate>
|
||||
<span>您有 10 个未读通知</span>
|
||||
</HeaderTemplate>
|
||||
@ -32,7 +32,7 @@
|
||||
@for (var index = 0; index < 10; index++)
|
||||
{
|
||||
<a class="dropdown-item d-flex align-items-center" href="#" @onclick:preventDefault>
|
||||
<i class="fa-solid fa-users text-primary"></i>
|
||||
<i class="fa fa-users text-primary"></i>
|
||||
<div class="ms-2">5 new members joined</div>
|
||||
</a>
|
||||
}
|
||||
@ -41,31 +41,31 @@
|
||||
<a href="#" @onclick:preventDefault>查看所有通知</a>
|
||||
</FooterTemplate>
|
||||
</DropdownWidgetItem>
|
||||
<DropdownWidgetItem Icon="fa-solid fa-flag" BadgeNumber="9" HeaderColor="Color.Danger" BadgeColor="Color.Danger">
|
||||
<DropdownWidgetItem Icon="fa-regular fa-flag" BadgeNumber="9" HeaderColor="Color.Danger" BadgeColor="Color.Danger">
|
||||
<HeaderTemplate>
|
||||
<span>您有 3 个任务</span>
|
||||
</HeaderTemplate>
|
||||
<BodyTemplate>
|
||||
<a href="#" class="dropdown-item" @onclick:preventDefault>
|
||||
<h3 class="position-relative">
|
||||
Design some buttons
|
||||
<small class="pull-right">20%</small>
|
||||
</h3>
|
||||
<BootstrapBlazor.Components.Progress IsAnimated="true" IsStriped="true" Value="20" Color="Color.Primary"></BootstrapBlazor.Components.Progress>
|
||||
<div class="d-flex">
|
||||
<div class="flex-fill pe-5">Design some buttons</div>
|
||||
<small>20%</small>
|
||||
</div>
|
||||
<Progress IsAnimated="true" IsStriped="true" Value="20" Color="Color.Primary"></Progress>
|
||||
</a>
|
||||
<a href="#" class="dropdown-item" @onclick:preventDefault>
|
||||
<h3 class="position-relative">
|
||||
Create a nice theme
|
||||
<small class="pull-right">40%</small>
|
||||
</h3>
|
||||
<BootstrapBlazor.Components.Progress Value="40" Color="Color.Success"></BootstrapBlazor.Components.Progress>
|
||||
<div class="d-flex">
|
||||
<div class="flex-fill pe-5">Create a nice theme</div>
|
||||
<small>40%</small>
|
||||
</div>
|
||||
<Progress Value="40" Color="Color.Success"></Progress>
|
||||
</a>
|
||||
<a href="#" class="dropdown-item" @onclick:preventDefault>
|
||||
<h3 class="position-relative">
|
||||
Some task I need to do
|
||||
<small class="pull-right">60%</small>
|
||||
</h3>
|
||||
<BootstrapBlazor.Components.Progress Value="60" Color="Color.Danger"></BootstrapBlazor.Components.Progress>
|
||||
<div class="d-flex">
|
||||
<div class="flex-fill pe-5">Some task I need to do</div>
|
||||
<small>60%</small>
|
||||
</div>
|
||||
<Progress Value="60" Color="Color.Danger"></Progress>
|
||||
</a>
|
||||
</BodyTemplate>
|
||||
<FooterTemplate>
|
||||
|
@ -1,16 +1,25 @@
|
||||
@inherits LayoutComponentBase
|
||||
@inject IOptionsMonitor<WebsiteOptions> WebsiteOption
|
||||
|
||||
<HeadContent>
|
||||
<link href="./css/layout.css" rel="stylesheet" />
|
||||
</HeadContent>
|
||||
|
||||
<CascadingValue Value="this" IsFixed="true">
|
||||
<Layout SideWidth="0" IsPage="true" IsFullSide="@IsFullSide" IsFixedHeader="@IsFixedHeader" IsFixedFooter="@IsFixedFooter"
|
||||
<Layout IsFullSide="@IsFullSide" IsFixedHeader="@IsFixedHeader" IsFixedFooter="@IsFixedFooter"
|
||||
ShowFooter="@ShowFooter" ShowGotoTop="true" ShowCollapseBar="true" Menus="@Menus"
|
||||
UseTabSet="@UseTabSet" TabDefaultUrl="layout-page" AdditionalAssemblies="new[] { GetType().Assembly }" class="@LayoutClassString">
|
||||
<Header>
|
||||
<span class="ms-3 flex-fill">Bootstrap of Blazor</span>
|
||||
<Widget></Widget>
|
||||
<img alt="avatar" src="./images/Argo-C.png" class="layout-avatar-right" />
|
||||
<span class="mx-3 d-none d-sm-block">超级管理员</span>
|
||||
<div class="layout-drawer" @onclick="@ToggleDrawer"><i class="fa-solid fa-gears"></i></div>
|
||||
<Logout ImageUrl="images/Argo-C.png" DisplayName="超级管理员" UserName="Admin">
|
||||
<LinkTemplate>
|
||||
<a href="#"><i class="fa-solid fa-suitcase"></i>个人中心</a>
|
||||
<a href="#"><i class="fa-solid fa-cog"></i>设置</a>
|
||||
<a href="#"><i class="fa-solid fa-bell"></i>通知<span class="badge badge-pill badge-success"></span></a>
|
||||
<LogoutLink />
|
||||
</LinkTemplate>
|
||||
</Logout>
|
||||
</Header>
|
||||
<Side>
|
||||
<div class="layout-banner">
|
||||
@ -29,110 +38,4 @@
|
||||
</div>
|
||||
</Footer>
|
||||
</Layout>
|
||||
|
||||
<Drawer Placement="Placement.Right" @bind-IsOpen="@IsOpen" IsBackdrop="true">
|
||||
<div class="layout-drawer-body">
|
||||
<div class="btn btn-info w-100" @onclick="@(e => IsOpen = false)">点击关闭</div>
|
||||
<div class="page-layout-demo-option">
|
||||
<p>布局调整</p>
|
||||
<div class="row">
|
||||
<div class="col-6">
|
||||
<Tooltip Title="左右结构">
|
||||
<div class="layout-item @(IsFullSide ? "active d-flex" : "d-flex")" @onclick="@(e => IsFullSide = true)">
|
||||
<div class="layout-left d-flex flex-column">
|
||||
<div class="layout-left-header"></div>
|
||||
<div class="layout-left-body flex-fill"></div>
|
||||
</div>
|
||||
<div class="layout-right d-flex flex-column flex-fill">
|
||||
<div class="layout-right-header"></div>
|
||||
<div class="layout-right-body flex-fill"></div>
|
||||
<div class="layout-right-footer"></div>
|
||||
</div>
|
||||
</div>
|
||||
</Tooltip>
|
||||
</div>
|
||||
<div class="col-6">
|
||||
<Tooltip Title="上下结构">
|
||||
<div class="layout-item flex-column @(IsFullSide ? "d-flex" : "active d-flex")" @onclick="@(e => IsFullSide = false)">
|
||||
<div class="layout-top">
|
||||
</div>
|
||||
<div class="layout-body d-flex flex-fill">
|
||||
<div class="layout-left">
|
||||
</div>
|
||||
<div class="layout-right flex-fill">
|
||||
</div>
|
||||
</div>
|
||||
<div class="layout-footer">
|
||||
</div>
|
||||
</div>
|
||||
</Tooltip>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="page-layout-demo-option">
|
||||
<p>固定调整</p>
|
||||
<div class="row">
|
||||
<div class="col-6 d-flex align-items-center">
|
||||
<Switch @bind-Value="@IsFixedHeader" OnColor="@Color.Success" OffColor="@Color.Secondary"></Switch>
|
||||
</div>
|
||||
<div class="col-6 text-end">
|
||||
<span>固定页头</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mt-3">
|
||||
<div class="col-6 d-flex align-items-center">
|
||||
<Switch @bind-Value="@IsFixedFooter" OnColor="@Color.Success" OffColor="@Color.Secondary"></Switch>
|
||||
</div>
|
||||
<div class="col-6 text-end">
|
||||
<span>固定页脚</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mt-3">
|
||||
<div class="col-6 d-flex align-items-center">
|
||||
<Switch @bind-Value="@ShowFooter" OnColor="@Color.Success" OffColor="@Color.Secondary"></Switch>
|
||||
</div>
|
||||
<div class="col-6 text-end">
|
||||
<span>显示页脚</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="page-layout-demo-option">
|
||||
<p>主题配色</p>
|
||||
<div class="row">
|
||||
<div class="col-2">
|
||||
<span class="color color1" @onclick="@(e => Theme = "color1")"></span>
|
||||
</div>
|
||||
<div class="col-2">
|
||||
<span class="color color2" @onclick="@(e => Theme = "color2")"></span>
|
||||
</div>
|
||||
<div class="col-2">
|
||||
<span class="color color3" @onclick="@(e => Theme = "color3")"></span>
|
||||
</div>
|
||||
<div class="col-2">
|
||||
<span class="color color4" @onclick="@(e => Theme = "color4")"></span>
|
||||
</div>
|
||||
<div class="col-2">
|
||||
<span class="color color5" @onclick="@(e => Theme = "color5")"></span>
|
||||
</div>
|
||||
<div class="col-2">
|
||||
<span class="color color6" @onclick="@(e => Theme = "color6")"></span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="page-layout-demo-option">
|
||||
<p>更多设置</p>
|
||||
<div class="row">
|
||||
<div class="col-6 d-flex align-items-center">
|
||||
<Switch @bind-Value="@UseTabSet" OnColor="@Color.Success" OffColor="@Color.Primary"></Switch>
|
||||
</div>
|
||||
<div class="col-6 text-end">
|
||||
<span>@(UseTabSet ? "多标签" : "单页")</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</Drawer>
|
||||
</CascadingValue>
|
||||
|
@ -24,37 +24,31 @@ public sealed partial class PageLayout
|
||||
/// <summary>
|
||||
/// 获得/设置 是否固定 TabHeader
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public bool IsFixedTab { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 获得/设置 是否固定页头
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public bool IsFixedHeader { get; set; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// 获得/设置 是否固定页脚
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public bool IsFixedFooter { get; set; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// 获得/设置 侧边栏是否外置
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public bool IsFullSide { get; set; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// 获得/设置 是否显示页脚
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public bool ShowFooter { get; set; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// 获得/设置 是否开启多标签模式
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public bool UseTabSet { get; set; } = true;
|
||||
|
||||
/// <summary>
|
||||
@ -80,9 +74,4 @@ public sealed partial class PageLayout
|
||||
/// 更新组件方法
|
||||
/// </summary>
|
||||
public void Update() => StateHasChanged();
|
||||
|
||||
private void ToggleDrawer()
|
||||
{
|
||||
IsOpen = !IsOpen;
|
||||
}
|
||||
}
|
||||
|
@ -1,310 +0,0 @@
|
||||
.layout-logo {
|
||||
border: solid 1px #fff;
|
||||
}
|
||||
|
||||
.color {
|
||||
width: 1.5rem;
|
||||
height: 1.5rem;
|
||||
display: block;
|
||||
cursor: pointer;
|
||||
border: 2px solid #e9ecef;
|
||||
border-radius: var(--bs-border-radius);
|
||||
transition: border .3s linear;
|
||||
}
|
||||
|
||||
.color:hover {
|
||||
border: 2px solid #28a745;
|
||||
}
|
||||
|
||||
.color1 {
|
||||
background-color: #409eff;
|
||||
}
|
||||
|
||||
.color2 {
|
||||
background-color: #28a745;
|
||||
}
|
||||
|
||||
.color3 {
|
||||
background-color: #e83e8c;
|
||||
}
|
||||
|
||||
.color4 {
|
||||
background-color: #ffe484;
|
||||
}
|
||||
|
||||
.color5 {
|
||||
background-color: #17a2b8;
|
||||
}
|
||||
|
||||
.color6 {
|
||||
background-color: #4a3275;
|
||||
}
|
||||
|
||||
.color1,
|
||||
.layout.is-page.color1 .layout-header {
|
||||
background-color: #409eff;
|
||||
}
|
||||
|
||||
.layout.is-page.color1 .layout-side .layout-banner {
|
||||
background-color: #3e84d0
|
||||
}
|
||||
|
||||
.layout.is-page.color1 .layout-side {
|
||||
background-color: #212529;
|
||||
color: var(--bb-disabled-bg);
|
||||
}
|
||||
|
||||
.layout.is-page.color1 .layout-footer {
|
||||
background-color: #343a40;
|
||||
}
|
||||
|
||||
.layout.is-page.color1 .layout-header-bar {
|
||||
background-color: #2b7cd0;
|
||||
border-color: #014186;
|
||||
}
|
||||
|
||||
.layout.is-page.color1 .layout-drawer:hover {
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.color2,
|
||||
.layout.is-page.color2 .layout-header {
|
||||
background-color: #28a745;
|
||||
}
|
||||
|
||||
.layout.is-page.color2 .layout-side .layout-banner {
|
||||
background-color: #24903d
|
||||
}
|
||||
|
||||
.layout.is-page.color2 .layout-side {
|
||||
background-color: #212529;
|
||||
color: var(--bb-disabled-bg);
|
||||
}
|
||||
|
||||
.layout.is-page.color2 .layout-footer {
|
||||
background-color: #343a40;
|
||||
}
|
||||
|
||||
.layout.is-page.color2 .layout-header-bar {
|
||||
background-color: #258c3c;
|
||||
border-color: #014186;
|
||||
}
|
||||
|
||||
.layout.is-page.color2 .layout-drawer:hover {
|
||||
background-color: #24903d;
|
||||
}
|
||||
|
||||
.color3,
|
||||
.layout.is-page.color3 .layout-header {
|
||||
background-color: #e83e8c;
|
||||
}
|
||||
|
||||
.layout.is-page.color3 .layout-side .layout-banner {
|
||||
background-color: #c5417e
|
||||
}
|
||||
|
||||
.layout.is-page.color3 .layout-side {
|
||||
background-color: #212529;
|
||||
color: var(--bb-disabled-bg);
|
||||
}
|
||||
|
||||
.layout.is-page.color3 .layout-footer {
|
||||
background-color: #343a40;
|
||||
}
|
||||
|
||||
.layout.is-page.color3 .layout-header-bar {
|
||||
background-color: #c73477;
|
||||
border-color: #014186;
|
||||
}
|
||||
|
||||
.layout.is-page.color3 .layout-drawer:hover {
|
||||
background-color: #c5417e;
|
||||
}
|
||||
|
||||
.color4,
|
||||
.layout.is-page.color4 .layout-header {
|
||||
background-color: #ffc107;
|
||||
}
|
||||
|
||||
.layout.is-page.color4 .layout-side .layout-banner {
|
||||
background-color: #e4af10
|
||||
}
|
||||
|
||||
.layout.is-page.color4 .layout-side {
|
||||
background-color: #212529;
|
||||
color: var(--bb-disabled-bg);
|
||||
}
|
||||
|
||||
.layout.is-page.color4 .layout-footer {
|
||||
background-color: #343a40;
|
||||
}
|
||||
|
||||
.layout.is-page.color4 .layout-header-bar {
|
||||
background-color: #e2b221;
|
||||
border-color: #014186;
|
||||
}
|
||||
|
||||
.layout.is-page.color4 .layout-drawer:hover {
|
||||
background-color: #e4af10;
|
||||
}
|
||||
|
||||
.color5,
|
||||
.layout.is-page.color5 .layout-header {
|
||||
background-color: #17a2b8;
|
||||
}
|
||||
|
||||
.color6,
|
||||
.layout.is-page.color6 .layout-header {
|
||||
background-color: #6610f2;
|
||||
}
|
||||
|
||||
.layout.is-page.color6 .layout-side .layout-banner {
|
||||
background-color: #4b0cb3
|
||||
}
|
||||
|
||||
.layout.is-page.color6 .layout-side {
|
||||
background-color: #212529;
|
||||
color: var(--bb-disabled-bg);
|
||||
}
|
||||
|
||||
.layout.is-page.color6 .layout-footer {
|
||||
background-color: #343a40;
|
||||
}
|
||||
|
||||
.layout.is-page.color6 .layout-header-bar {
|
||||
background-color: #4b0ab5;
|
||||
border-color: #014186;
|
||||
}
|
||||
|
||||
.layout.is-page.color6 .layout-drawer:hover {
|
||||
background-color: #4b0cb3;
|
||||
}
|
||||
|
||||
.layout-drawer {
|
||||
padding: 13px;
|
||||
margin-inline-end: -1rem;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.layout-drawer:hover {
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.layout-drawer-body {
|
||||
padding: 1rem;
|
||||
}
|
||||
|
||||
.layout-item {
|
||||
cursor: pointer;
|
||||
border: 2px solid #e9ecef;
|
||||
padding: 4px;
|
||||
border-radius: var(--bs-border-radius);
|
||||
height: 80px;
|
||||
width: 120px;
|
||||
transition: border .3s linear;
|
||||
}
|
||||
|
||||
.layout-item:hover,
|
||||
.layout-item.active {
|
||||
border: 2px solid #28a745;
|
||||
}
|
||||
|
||||
.layout-item .layout-left {
|
||||
width: 30%;
|
||||
}
|
||||
|
||||
.layout-item .layout-left .layout-left-header {
|
||||
height: 16px;
|
||||
background-color: var(--bb-layout-sidebar-banner-background);
|
||||
}
|
||||
|
||||
.layout-item .layout-left .layout-left-body,
|
||||
.layout-item .layout-body .layout-left {
|
||||
background-color: #2f4050;
|
||||
}
|
||||
|
||||
.layout-item .layout-right .layout-right-header,
|
||||
.layout-item .layout-top {
|
||||
background-color: #17a2b8;
|
||||
height: 16px;
|
||||
}
|
||||
|
||||
.layout-item .layout-right .layout-right-footer,
|
||||
.layout-item .layout-footer {
|
||||
background-color: #5b6e84;
|
||||
height: 12px;
|
||||
}
|
||||
|
||||
.layout-item .layout-top,
|
||||
.layout-item .layout-body,
|
||||
.layout-item .layout-footer {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.layout.is-page .layout-right {
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
::deep + .widget .dropdown-body h3 {
|
||||
color: #666666;
|
||||
font-size: 14px;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
::deep + .widget .dropdown-body h4 {
|
||||
color: #444444;
|
||||
font-size: 15px;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
::deep + .widget .dropdown-body small {
|
||||
color: #999999;
|
||||
font-size: 10px;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
}
|
||||
|
||||
::deep + .widget .dropdown-item > div:not(.progress):last-child {
|
||||
width: calc(100% - 40px);
|
||||
}
|
||||
|
||||
::deep + .widget .dropdown-item {
|
||||
padding: 0.5rem 1rem;
|
||||
}
|
||||
|
||||
::deep + .widget .progress {
|
||||
height: 7px;
|
||||
}
|
||||
|
||||
::deep + .widget .dropdown-item.active,
|
||||
::deep + .widget .dropdown-item:active {
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
::deep + .widget .dropdown-item:not(:nth-of-type(odd)):active {
|
||||
background-color: inherit;
|
||||
}
|
||||
|
||||
.page-layout-demo-option {
|
||||
margin-top: 1.5rem;
|
||||
border: 1px solid rgba(0,0,0,.125);
|
||||
border-radius: var(--bs-border-radius);
|
||||
padding: 1.5rem 1rem 1rem 1rem;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.page-layout-demo-option > p {
|
||||
position: absolute;
|
||||
top: -10px;
|
||||
padding: 0 0.5rem;
|
||||
background: #fff;
|
||||
}
|
||||
|
||||
.page-layout-demo-option .tabs-body-content {
|
||||
margin: 0 -1rem -2rem -1rem;
|
||||
}
|
||||
|
||||
.page-layout-demo-footer-link {
|
||||
color: #fff;
|
||||
}
|
@ -11,7 +11,7 @@
|
||||
<p>@Localizer["P1"] <code>Layout</code> @Localizer["P2"] <code>dotnet new bbapp</code> @Localizer["P3"] <code>Visual Studio</code> @Localizer["P4"] <code>@Localizer["P5"]</code> @Localizer["P6"] <a href="template" target="_blank">[@Localizer["P7"]]</a></p>
|
||||
<div>
|
||||
<b class="mb-3">@Localizer["P8"]:</b>
|
||||
<code>Layout</code> @Localizer["P9"] <code>@Localizer["P10"]</code> @Localizer["P11"] <code>@Localizer["P12"]</code> @Localizer["P13"] <code>AdditionalAssemblies</code> @Localizer["P14"] <a href="https://docs.microsoft.com/en-us/aspnet/core/blazor/fundamentals/routing?view=aspnetcore-3.1#route-to-components-from-multiple-assemblies" target="_blank">[@Localizer["P15"]]</a>
|
||||
<code>Layout</code> @Localizer["P9"] <code>@Localizer["P10"]</code> @Localizer["P11"] <code>@Localizer["P12"]</code> @Localizer["P13"] <code>AdditionalAssemblies</code> @Localizer["P14"] <a href="https://docs.microsoft.com/en-us/aspnet/core/blazor/fundamentals/routing?#route-to-components-from-multiple-assemblies" target="_blank">[@Localizer["P15"]]</a>
|
||||
</div>
|
||||
</Tips>
|
||||
|
||||
@ -19,31 +19,31 @@
|
||||
<p>@Localizer["P16"]</p>
|
||||
<div class="row">
|
||||
<div class="col-12">
|
||||
<RadioList TValue="SelectedItem" Items="@SideBarItems" OnSelectedChanged="@OnSideChanged" />
|
||||
<RadioList Value="ActiveItem" Items="@SideBarItems" OnSelectedChanged="@OnSideChanged" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mt-3">
|
||||
<div class="col-12">
|
||||
<Checkbox @bind-Value="ShowFooter" OnStateChanged="OnFooterChanged" ShowAfterLabel="true" DisplayText="@Localizer["P17"]" />
|
||||
<Checkbox Value="ShowFooter" OnValueChanged="OnFooterChanged" ShowAfterLabel="true" DisplayText="@Localizer["P17"]" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mt-3">
|
||||
<div class="col-12">
|
||||
<Switch @bind-Value="@UseTabSet" OnText="@Localizer["P18"]" OffText="@Localizer["P19"]" OnColor="@Color.Success" OffColor="@Color.Secondary" style="width: 120px;" OnValueChanged="OnUseTabSetChanged"></Switch>
|
||||
<Switch Value="@UseTabSet" OnText="@Localizer["P18"]" OffText="@Localizer["P19"]" OnColor="@Color.Success" OffColor="@Color.Secondary" style="width: 120px;" OnValueChanged="OnUseTabSetChanged"></Switch>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="page-layout-demo-option">
|
||||
<p>@Localizer["P20"]</p>
|
||||
<Checkbox @bind-Value="@IsFixedTab" OnStateChanged="@OnTabStateChanged" ShowAfterLabel="true" DisplayText="@Localizer["P21"]" />
|
||||
<Checkbox @bind-Value="@IsFixedHeader" OnStateChanged="@OnHeaderStateChanged" IsDisabled="IsFixedTab" ShowAfterLabel="true" DisplayText="@Localizer["P22"]" class="mx-3" />
|
||||
<Checkbox @bind-Value="@IsFixedFooter" OnStateChanged="@OnFooterStateChanged" IsDisabled="IsFixedTab" ShowAfterLabel="true" DisplayText="@Localizer["P23"]" />
|
||||
<Checkbox Value="@IsFixedTab" OnStateChanged="@OnTabStateChanged" ShowAfterLabel="true" DisplayText="@Localizer["P21"]" />
|
||||
<Checkbox Value="@IsFixedHeader" OnStateChanged="@OnHeaderStateChanged" IsDisabled="IsFixedTab" ShowAfterLabel="true" DisplayText="@Localizer["P22"]" class="mx-3" />
|
||||
<Checkbox Value="@IsFixedFooter" OnStateChanged="@OnFooterStateChanged" IsDisabled="IsFixedTab" ShowAfterLabel="true" DisplayText="@Localizer["P23"]" />
|
||||
</div>
|
||||
|
||||
<div class="page-layout-demo-option">
|
||||
<p>@Localizer["P24"]</p>
|
||||
<div>@Localizer["P25"] <code>Header</code> @Localizer["P26"]</div>
|
||||
<div>@Localizer["P25"] <code>Header</code> @((MarkupString)Localizer["P26"].Value)</div>
|
||||
</div>
|
||||
|
||||
<div class="page-layout-demo-option">
|
||||
|
@ -10,11 +10,14 @@ namespace BootstrapBlazor.Server.Components.Samples;
|
||||
/// </summary>
|
||||
public sealed partial class LayoutPages
|
||||
{
|
||||
private IEnumerable<SelectedItem> SideBarItems { get; set; } = new SelectedItem[]
|
||||
{
|
||||
new SelectedItem("left-right", "左右结构"),
|
||||
new SelectedItem("top-bottom", "上下结构")
|
||||
};
|
||||
private List<SelectedItem> SideBarItems { get; } =
|
||||
[
|
||||
new("left-right", "左右结构"),
|
||||
new("top-bottom", "上下结构")
|
||||
];
|
||||
|
||||
[NotNull]
|
||||
private SelectedItem? ActiveItem { get; set; }
|
||||
|
||||
private string? StyleString => CssBuilder.Default()
|
||||
.AddClass($"height: {Height * 100}px", Height > 0)
|
||||
@ -63,9 +66,9 @@ public sealed partial class LayoutPages
|
||||
/// <summary>
|
||||
/// OnInitialized 方法
|
||||
/// </summary>
|
||||
protected override async Task OnInitializedAsync()
|
||||
protected override void OnInitialized()
|
||||
{
|
||||
await base.OnInitializedAsync();
|
||||
base.OnInitialized();
|
||||
|
||||
IsFullSide = RootPage.IsFullSide;
|
||||
IsFixedHeader = RootPage.IsFixedHeader;
|
||||
@ -73,44 +76,67 @@ public sealed partial class LayoutPages
|
||||
ShowFooter = RootPage.ShowFooter;
|
||||
UseTabSet = RootPage.UseTabSet;
|
||||
|
||||
SideBarItems.ElementAt(IsFullSide ? 0 : 1).Active = true;
|
||||
ActiveItem = IsFullSide ? SideBarItems[0] : SideBarItems[1];
|
||||
}
|
||||
|
||||
private Task OnFooterChanged(CheckboxState state, bool val) => UpdateAsync();
|
||||
|
||||
private Task OnTabStateChanged(CheckboxState state, bool val) => UpdateAsync();
|
||||
|
||||
private Task OnHeaderStateChanged(CheckboxState state, bool val) => UpdateAsync();
|
||||
|
||||
private Task OnFooterStateChanged(CheckboxState state, bool val) => UpdateAsync();
|
||||
|
||||
private async Task OnSideChanged(IEnumerable<SelectedItem> values, SelectedItem item)
|
||||
private Task OnFooterChanged(bool val)
|
||||
{
|
||||
IsFullSide = item.Value == "left-right";
|
||||
await UpdateAsync();
|
||||
ShowFooter = val;
|
||||
Update();
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
private Task OnUseTabSetChanged(bool val) => UpdateAsync();
|
||||
private Task OnTabStateChanged(CheckboxState state, bool val)
|
||||
{
|
||||
IsFixedTab = val;
|
||||
Update();
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
private Task OnHeaderStateChanged(CheckboxState state, bool val)
|
||||
{
|
||||
IsFixedHeader = val;
|
||||
Update();
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
private Task OnFooterStateChanged(CheckboxState state, bool val)
|
||||
{
|
||||
IsFixedFooter = val;
|
||||
Update();
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
private Task OnSideChanged(IEnumerable<SelectedItem> values, SelectedItem item)
|
||||
{
|
||||
ActiveItem.Active = false;
|
||||
item.Active = true;
|
||||
ActiveItem = item;
|
||||
IsFullSide = item.Value == "left-right";
|
||||
Update();
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
private Task OnUseTabSetChanged(bool val)
|
||||
{
|
||||
UseTabSet = val;
|
||||
Update();
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// UpdateAsync 方法
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public async Task UpdateAsync()
|
||||
public void Update()
|
||||
{
|
||||
var parameters = new Dictionary<string, object?>()
|
||||
{
|
||||
[nameof(RootPage.IsFullSide)] = IsFullSide,
|
||||
[nameof(RootPage.IsFixedFooter)] = IsFixedFooter && ShowFooter,
|
||||
[nameof(RootPage.IsFixedHeader)] = IsFixedHeader,
|
||||
[nameof(RootPage.IsFixedTab)] = IsFixedTab,
|
||||
[nameof(RootPage.ShowFooter)] = ShowFooter,
|
||||
[nameof(RootPage.UseTabSet)] = UseTabSet
|
||||
};
|
||||
|
||||
await RootPage.SetParametersAsync(ParameterView.FromDictionary(parameters));
|
||||
|
||||
// 获得 Razor 示例代码
|
||||
RootPage.IsFullSide = IsFullSide;
|
||||
RootPage.IsFixedFooter = IsFixedFooter && ShowFooter;
|
||||
RootPage.IsFixedHeader = IsFixedHeader;
|
||||
RootPage.IsFixedTab = IsFixedTab;
|
||||
RootPage.ShowFooter = ShowFooter;
|
||||
RootPage.UseTabSet = UseTabSet;
|
||||
StateHasChanged();
|
||||
RootPage.Update();
|
||||
}
|
||||
|
||||
|
@ -81,14 +81,6 @@ public sealed partial class Layouts
|
||||
DefaultValue = "false"
|
||||
},
|
||||
new()
|
||||
{
|
||||
Name = "IsPage",
|
||||
Description = Localizer["Layouts_IsPage_Description"],
|
||||
Type = "bool",
|
||||
ValueList = "true|false",
|
||||
DefaultValue = "false"
|
||||
},
|
||||
new()
|
||||
{
|
||||
Name = "IsFixedFooter",
|
||||
Description = Localizer["Layouts_IsFixedFooter_Description"],
|
||||
|
@ -62,7 +62,7 @@
|
||||
</Tips>
|
||||
<p>@((MarkupString)Localizer["MenusClickShrinkDescription"].Value)</p>
|
||||
<div class="layout-menu-demo">
|
||||
<Layout SideWidth="0" IsFullSide="true" ShowFooter="true" ShowCollapseBar="true" Menus="IconSideMenuItems">
|
||||
<Layout IsFullSide="true" ShowFooter="true" ShowCollapseBar="true" Menus="IconSideMenuItems">
|
||||
<Header>
|
||||
<div class="menu-demo-header">
|
||||
@Localizer["MenusClickShrinkSpanSpan"]
|
||||
|
@ -1418,7 +1418,7 @@
|
||||
"P23": "fixed footer",
|
||||
"P24": "Shrink adjustment",
|
||||
"P25": "Please click",
|
||||
"P26": "small green button in",
|
||||
"P26": "small <b>button</b>",
|
||||
"P27": "height adjustment",
|
||||
"P28": "view height",
|
||||
"P29": "Tab Test",
|
||||
@ -1468,7 +1468,6 @@
|
||||
"Layouts_Footer_Description": "Footer component template",
|
||||
"Layouts_Menus_Description": "Sidebar menu data collection when the whole page is laid out",
|
||||
"Layouts_IsFullSide_Description": "Whether the sidebar occupies the entire left",
|
||||
"Layouts_IsPage_Description": "Whether it is the whole page layout",
|
||||
"Layouts_IsFixedFooter_Description": "Whether to fix the Footer component",
|
||||
"Layouts_IsFixedHeader_Description": "Whether to fix the Header component",
|
||||
"Layouts_ShowCollapseBar_Description": "Whether to show contraction and expansion Bar",
|
||||
@ -2034,7 +2033,7 @@
|
||||
"TabsTipsTitle": "<code>Tab</code> components are generally used in two ways:",
|
||||
"TabsTips1": "Split as data",
|
||||
"TabsTips2": "Page navigation",
|
||||
"TabsTips3": "The default behavior of this component is data segmentation,Clicking on the <code>TabItem</code> title does not navigate, and if you need to navigate the address bar, set the <code>ClickTabToNavigation</code> property to <code>true</code>,When you click on the <code>TabItem</code> title, the address bar redirects navigation, mostly for the background management system to be used in conjunction with the <code>Menu</code> components,The actual combat can refer to the <code>multi-label</code> mode in the <a href='layout-page' target='_blank'>background template simulator</a>, When you have <code>Razor Component</code> in the additional Assemblies, set the <code>AdditionalAssemblies</code> property value correctly so that the route within the label component is resolved correctly, and the relevant documentation <a href='https://docs.microsoft.com/zh-cn/aspnet/core/blazor/fundamentals/routing?WT.mc_id-DT-MVP-5004174-view-aspnetcore-3.1-route-to-components-from-multiple-assemblies' target='_blank'>[Portal]</a>",
|
||||
"TabsTips3": "The default behavior of this component is data segmentation,Clicking on the <code>TabItem</code> title does not navigate, and if you need to navigate the address bar, set the <code>ClickTabToNavigation</code> property to <code>true</code>,When you click on the <code>TabItem</code> title, the address bar redirects navigation, mostly for the background management system to be used in conjunction with the <code>Menu</code> components,The actual combat can refer to the <code>multi-label</code> mode in the <a href='layout-page' target='_blank'>background template simulator</a>, When you have <code>Razor Component</code> in the additional Assemblies, set the <code>AdditionalAssemblies</code> property value correctly so that the route within the label component is resolved correctly, and the relevant documentation <a href='https://learn.microsoft.com/aspnet/core/blazor/fundamentals/routing?wt.mc_id=DT-MVP-5004174' target='_blank'>[Portal]</a>",
|
||||
"TabsTips4": "This component adapts to width height, etc., and scroll arrows can appear left and right or up and down when appropriate",
|
||||
"TabsInfoTitle": "Set additional information during tab navigation",
|
||||
"TabsItemMenuTitle": "Configure Tab and Menu linked dictionary, this method can automatically obtain tab page properties without separately setting TabItemOption.",
|
||||
|
@ -1418,7 +1418,7 @@
|
||||
"P23": "固定页脚",
|
||||
"P24": "收缩调整",
|
||||
"P25": "请点击",
|
||||
"P26": "中的绿色小按钮",
|
||||
"P26": "中的 <b>按钮</b>",
|
||||
"P27": "高度调整",
|
||||
"P28": "视图高度",
|
||||
"P29": "Tab 测试",
|
||||
@ -1468,7 +1468,6 @@
|
||||
"Layouts_Footer_Description": "页脚组件模板",
|
||||
"Layouts_Menus_Description": "整页面布局时侧边栏菜单数据集合",
|
||||
"Layouts_IsFullSide_Description": "侧边栏是否占满整个左边",
|
||||
"Layouts_IsPage_Description": "是否为整页面布局",
|
||||
"Layouts_IsFixedFooter_Description": "是否固定 Footer 组件",
|
||||
"Layouts_IsFixedHeader_Description": "是否固定 Header 组件",
|
||||
"Layouts_ShowCollapseBar_Description": "是否显示收缩展开 Bar",
|
||||
@ -2034,7 +2033,7 @@
|
||||
"TabsTipsTitle": "<code>Tab</code> 组件一般有两种用法:",
|
||||
"TabsTips1": "作为数据分割",
|
||||
"TabsTips2": "页面导航",
|
||||
"TabsTips3": "本组件默认行为为数据分割,点击 <code>TabItem</code> 标题时并不会进行导航行为,如果需要进行地址栏导航时请设置 <code>ClickTabToNavigation</code> 属性为 <code>true</code>,此时点击 <code>TabItem</code> 标题时地址栏将会重定向导航,多用于后台管理系统与 <code>Menu</code> 组件进行联动使用,实战可参考 <a href='layout-page' target='_blank'>后台模板模拟器</a> 中的 <code>多标签</code> 模式,如果有 <code>Razor 组件</code> 在额外的程序集中时,请正确设置 <code>AdditionalAssemblies</code> 属性值,以便标签组件内路由正确解析,相关文档 <a href='https://docs.microsoft.com/zh-cn/aspnet/core/blazor/fundamentals/routing?WT.mc_id=DT-MVP-5004174&view=aspnetcore-3.1#route-to-components-from-multiple-assemblies' target='_blank'>[传送门]</a>",
|
||||
"TabsTips3": "本组件默认行为为数据分割,点击 <code>TabItem</code> 标题时并不会进行导航行为,如果需要进行地址栏导航时请设置 <code>ClickTabToNavigation</code> 属性为 <code>true</code>,此时点击 <code>TabItem</code> 标题时地址栏将会重定向导航,多用于后台管理系统与 <code>Menu</code> 组件进行联动使用,实战可参考 <a href='layout-page' target='_blank'>后台模板模拟器</a> 中的 <code>多标签</code> 模式,如果有 <code>Razor 组件</code> 在额外的程序集中时,请正确设置 <code>AdditionalAssemblies</code> 属性值,以便标签组件内路由正确解析,相关文档 <a href='https://learn.microsoft.com/zh-cn/aspnet/core/blazor/fundamentals/routing?wt.mc_id=DT-MVP-5004174' target='_blank'>[传送门]</a>",
|
||||
"TabsTips4": "本组件会根据宽度高度等进行自适应适配,适当的时候可以出现左右或者上下的滚动箭头",
|
||||
"TabsInfoTitle": "标签页导航时设置附加信息",
|
||||
"TabsItemMenuTitle": "配置 Tab 与 Menu 联动字典,该方法无需再单独设置 TabItemOption 即可自动获取标签页属性。",
|
||||
|
80
src/BootstrapBlazor.Server/wwwroot/css/layout.css
Normal file
80
src/BootstrapBlazor.Server/wwwroot/css/layout.css
Normal file
@ -0,0 +1,80 @@
|
||||
.layout {
|
||||
--bb-layout-headerbar-background: var(--bb-primary-color);
|
||||
--bb-layout-logo-bg: var(--bb-primary-color);
|
||||
}
|
||||
|
||||
.layout-drawer {
|
||||
padding: 13px;
|
||||
margin-inline-end: -1rem;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.layout-drawer:hover {
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.layout-item {
|
||||
cursor: pointer;
|
||||
border: 2px solid #e9ecef;
|
||||
padding: 4px;
|
||||
border-radius: var(--bs-border-radius);
|
||||
height: 80px;
|
||||
width: 120px;
|
||||
transition: border .3s linear;
|
||||
}
|
||||
|
||||
.layout-item:hover,
|
||||
.layout-item.active {
|
||||
border: 2px solid #28a745;
|
||||
}
|
||||
|
||||
.layout-item .layout-left {
|
||||
width: 30%;
|
||||
}
|
||||
|
||||
.layout-item .layout-left .layout-left-header {
|
||||
height: 16px;
|
||||
background-color: var(--bb-layout-sidebar-banner-background);
|
||||
}
|
||||
|
||||
.layout-item .layout-left .layout-left-body,
|
||||
.layout-item .layout-body .layout-left {
|
||||
background-color: #2f4050;
|
||||
}
|
||||
|
||||
.layout-item .layout-right .layout-right-header,
|
||||
.layout-item .layout-top {
|
||||
background-color: #17a2b8;
|
||||
height: 16px;
|
||||
}
|
||||
|
||||
.layout-item .layout-right .layout-right-footer,
|
||||
.layout-item .layout-footer {
|
||||
background-color: #5b6e84;
|
||||
height: 12px;
|
||||
}
|
||||
|
||||
.layout-item .layout-top,
|
||||
.layout-item .layout-body,
|
||||
.layout-item .layout-footer {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.page-layout-demo-option {
|
||||
margin-top: 1.5rem;
|
||||
border: 1px solid rgba(0,0,0,.125);
|
||||
border-radius: var(--bs-border-radius);
|
||||
padding: 1.5rem 1rem 1rem 1rem;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.page-layout-demo-option > p {
|
||||
position: absolute;
|
||||
top: -10px;
|
||||
padding: 0 0.5rem;
|
||||
background: #fff;
|
||||
}
|
||||
|
||||
.page-layout-demo-option .tabs-body-content {
|
||||
margin: 0 -1rem -2rem -1rem;
|
||||
}
|
@ -71,6 +71,7 @@ h3, h4, h5 {
|
||||
|
||||
.layout {
|
||||
--bb-footer-height: 0px;
|
||||
--bb-layout-menu-item-hover-bg: var(--bb-primary-color);
|
||||
}
|
||||
|
||||
.layout.has-footer {
|
||||
|
@ -1,4 +1,4 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk.Razor">
|
||||
<Project Sdk="Microsoft.NET.Sdk.Razor">
|
||||
|
||||
<PropertyGroup>
|
||||
<Version>9.0.1-beta02</Version>
|
||||
|
@ -10,7 +10,7 @@
|
||||
<section @attributes="AdditionalAttributes" class="@ClassString" style="@StyleString">
|
||||
@if (Side == null)
|
||||
{
|
||||
if(Header != null)
|
||||
if (Header != null)
|
||||
{
|
||||
@RenderHeader(false)
|
||||
}
|
||||
@ -23,7 +23,7 @@
|
||||
else if (IsFullSide)
|
||||
{
|
||||
<aside class="@SideClassString" style="@SideStyleString">
|
||||
@if(Side != null)
|
||||
@if (Side != null)
|
||||
{
|
||||
@Side
|
||||
}
|
||||
@ -33,7 +33,7 @@
|
||||
}
|
||||
</aside>
|
||||
<section class="layout-right">
|
||||
@if(Header != null)
|
||||
@if (Header != null)
|
||||
{
|
||||
@RenderHeader(ShowCollapseBar)
|
||||
}
|
||||
@ -88,9 +88,9 @@
|
||||
{
|
||||
@if (CollapseBarTemplate == null)
|
||||
{
|
||||
<a title="" data-bs-toggle="tooltip" data-bs-placement="right" data-bs-original-title="@TooltipText" class="@CollapseBarClassString" @onclick="CollapseMenu">
|
||||
<div data-bs-toggle="tooltip" data-bs-placement="right" data-bs-original-title="@TooltipText" class="layout-header-bar" @onclick="ToggleSidebar">
|
||||
<i class="@MenuBarIcon"></i>
|
||||
</a>
|
||||
</div>
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -105,17 +105,17 @@
|
||||
@if (hasScroll)
|
||||
{
|
||||
<Scroll>
|
||||
<Menu Items="@Menus" IsVertical="true" IsCollapsed="@IsCollapsed" IsAccordion="@IsAccordion" OnClick="@ClickMenu()"></Menu>
|
||||
<Menu Items="@Menus" IsVertical="true" IsAccordion="@IsAccordion" OnClick="ClickMenu"></Menu>
|
||||
</Scroll>
|
||||
}
|
||||
else
|
||||
{
|
||||
<Menu Items="@Menus" IsVertical="true" IsCollapsed="@IsCollapsed" IsAccordion="@IsAccordion" OnClick="@ClickMenu()"></Menu>
|
||||
<Menu Items="@Menus" IsVertical="true" IsAccordion="@IsAccordion" OnClick="ClickMenu"></Menu>
|
||||
}
|
||||
</div>;
|
||||
|
||||
RenderFragment RenderMain =>
|
||||
@<main class="@MainClassString">
|
||||
@<main class="layout-main">
|
||||
@if (UseTabSet)
|
||||
{
|
||||
<Tab ClickTabToNavigation="ClickTabToNavigation" AdditionalAssemblies="@AdditionalAssemblies"
|
||||
|
@ -3,7 +3,6 @@
|
||||
// See the LICENSE file in the project root for more information.
|
||||
// Maintainer: Argo Zhang(argo@live.ca) Website: https://www.blazor.zone
|
||||
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Components.Authorization;
|
||||
using Microsoft.AspNetCore.Components.Routing;
|
||||
using Microsoft.Extensions.Localization;
|
||||
@ -109,6 +108,8 @@ public partial class Layout : IHandlerException
|
||||
/// </summary>
|
||||
/// <remarks>为真时增加 is-page 样式</remarks>
|
||||
[Parameter]
|
||||
[Obsolete("已弃用,直接删除即可;Deprecated Please remove it")]
|
||||
[ExcludeFromCodeCoverage]
|
||||
public bool IsPage { get; set; }
|
||||
|
||||
/// <summary>
|
||||
@ -233,8 +234,8 @@ public partial class Layout : IHandlerException
|
||||
/// </summary>
|
||||
private string? ClassString => CssBuilder.Default("layout")
|
||||
.AddClass("has-sidebar", Side != null && IsFullSide)
|
||||
.AddClass("is-page", IsPage)
|
||||
.AddClass("has-footer", ShowFooter && Footer != null)
|
||||
.AddClass("is-collapsed", IsCollapsed)
|
||||
.AddClassFromAttributes(AdditionalAttributes)
|
||||
.Build();
|
||||
|
||||
@ -249,7 +250,6 @@ public partial class Layout : IHandlerException
|
||||
/// </summary>
|
||||
private string? FooterClassString => CssBuilder.Default("layout-footer")
|
||||
.AddClass("is-fixed", IsFixedFooter)
|
||||
.AddClass("is-collapsed", IsCollapsed)
|
||||
.Build();
|
||||
|
||||
/// <summary>
|
||||
@ -263,7 +263,6 @@ public partial class Layout : IHandlerException
|
||||
/// 获得 侧边栏样式
|
||||
/// </summary>
|
||||
private string? SideClassString => CssBuilder.Default("layout-side")
|
||||
.AddClass("is-collapsed", IsCollapsed)
|
||||
.AddClass("is-fixed-header", IsFixedHeader)
|
||||
.AddClass("is-fixed-footer", IsFixedFooter)
|
||||
.Build();
|
||||
@ -272,21 +271,7 @@ public partial class Layout : IHandlerException
|
||||
/// 获得 侧边栏 Style 字符串
|
||||
/// </summary>
|
||||
private string? SideStyleString => CssBuilder.Default()
|
||||
.AddClass($"width: {SideWidth.ConvertToPercentString()}", !IsCollapsed && !string.IsNullOrEmpty(SideWidth) && SideWidth != "0")
|
||||
.Build();
|
||||
|
||||
/// <summary>
|
||||
/// 获得 Main 样式
|
||||
/// </summary>
|
||||
private string? MainClassString => CssBuilder.Default("layout-main")
|
||||
.AddClass("is-collapsed", IsCollapsed)
|
||||
.Build();
|
||||
|
||||
/// <summary>
|
||||
/// 获得 展开收缩 Bar 样式
|
||||
/// </summary>
|
||||
private string? CollapseBarClassString => CssBuilder.Default("layout-header-bar")
|
||||
.AddClass("is-collapsed", IsCollapsed)
|
||||
.AddClass($"--bb-layout-sidebar-width: {SideWidth.ConvertToPercentString()}", !string.IsNullOrEmpty(SideWidth) && SideWidth != "0")
|
||||
.Build();
|
||||
|
||||
/// <summary>
|
||||
@ -336,6 +321,8 @@ public partial class Layout : IHandlerException
|
||||
|
||||
private bool _init { get; set; }
|
||||
|
||||
//private bool _isInteractive = true;
|
||||
|
||||
/// <summary>
|
||||
/// <inheritdoc/>
|
||||
/// </summary>
|
||||
@ -350,6 +337,10 @@ public partial class Layout : IHandlerException
|
||||
}
|
||||
|
||||
ErrorLogger?.Register(this);
|
||||
|
||||
#if NET9_0_OR_GREATER
|
||||
//_isInteractive = RendererInfo.IsInteractive;
|
||||
#endif
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -395,8 +386,6 @@ public partial class Layout : IHandlerException
|
||||
base.OnParametersSet();
|
||||
|
||||
TooltipText ??= Localizer[nameof(TooltipText)];
|
||||
SideWidth ??= "300";
|
||||
|
||||
MenuBarIcon ??= IconTheme.GetIconByKey(ComponentIcons.LayoutMenuBarIcon);
|
||||
}
|
||||
|
||||
@ -455,12 +444,26 @@ public partial class Layout : IHandlerException
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 点击 收缩展开按钮时回调此方法
|
||||
/// 点击菜单时回调此方法
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
private async Task CollapseMenu()
|
||||
private async Task ClickMenu(MenuItem item)
|
||||
{
|
||||
// 小屏幕时生效
|
||||
if (IsSmallScreen && !item.Items.Any())
|
||||
{
|
||||
IsCollapsed = false;
|
||||
await TriggerCollapseChanged();
|
||||
}
|
||||
|
||||
if (OnClickMenu != null)
|
||||
{
|
||||
await OnClickMenu(item);
|
||||
}
|
||||
}
|
||||
|
||||
private async Task TriggerCollapseChanged()
|
||||
{
|
||||
IsCollapsed = !IsCollapsed;
|
||||
if (IsCollapsedChanged.HasDelegate)
|
||||
{
|
||||
await IsCollapsedChanged.InvokeAsync(IsCollapsed);
|
||||
@ -472,23 +475,12 @@ public partial class Layout : IHandlerException
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 点击菜单时回调此方法
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
private Func<MenuItem, Task> ClickMenu() => async item =>
|
||||
private async Task ToggleSidebar()
|
||||
{
|
||||
// 小屏幕时生效
|
||||
if (IsSmallScreen && !item.Items.Any())
|
||||
{
|
||||
await CollapseMenu();
|
||||
}
|
||||
IsCollapsed = !IsCollapsed;
|
||||
|
||||
if (OnClickMenu != null)
|
||||
{
|
||||
await OnClickMenu(item);
|
||||
}
|
||||
};
|
||||
await TriggerCollapseChanged();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 上次渲染错误内容
|
||||
|
@ -10,7 +10,7 @@ export function init(id, invoke, callback) {
|
||||
}
|
||||
Data.set(id, layout)
|
||||
|
||||
const tooltip = document.querySelector('.layout-header [data-bs-toggle="tooltip"]')
|
||||
const tooltip = document.querySelector('.layout-header-bar')
|
||||
if (tooltip) {
|
||||
layout.tooltip = bootstrap.Tooltip.getOrCreateInstance(tooltip)
|
||||
}
|
||||
|
@ -42,166 +42,139 @@
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
flex-direction: column;
|
||||
position: relative;
|
||||
|
||||
.layout-main {
|
||||
flex: 1;
|
||||
.layout-banner {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 0 0.625rem;
|
||||
height: var(--bb-layout-header-height);
|
||||
font-size: var(--bb-layout-banner-font-size);
|
||||
border-bottom: 1px solid var(--bb-layout-banner-border-color);
|
||||
background-color: var(--bb-layout-sidebar-banner-background);
|
||||
|
||||
.layout-title {
|
||||
display: inline-block;
|
||||
color: var(--bb-layout-title-color);
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
flex: 1 1 auto;
|
||||
opacity: 1;
|
||||
transition: opacity .3s linear;
|
||||
}
|
||||
|
||||
.layout-logo {
|
||||
width: var(--bb-layout-banner-logo-width);
|
||||
border-radius: var(--bs-border-radius);
|
||||
background-color: var(--bb-layout-logo-bg);
|
||||
border: 1px solid var(--bb-layout-logo-border-color);
|
||||
|
||||
+ .layout-title {
|
||||
margin-left: var(--bb-layout-title-margin-left);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&.is-page {
|
||||
.layout-side {
|
||||
transform: translateX(-100%);
|
||||
position: fixed;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
width: auto;
|
||||
transition: transform .3s linear;
|
||||
z-index: 1030;
|
||||
background-color: var(--bb-layout-sidebar-background);
|
||||
color: var(--bb-layout-sidebar-color);
|
||||
.has-sidebar {
|
||||
/*left-right*/
|
||||
position: relative;
|
||||
flex: 1;
|
||||
|
||||
&.is-collapsed {
|
||||
transform: translateX(0);
|
||||
}
|
||||
|
||||
.layout-banner {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 0 0.625rem;
|
||||
background-color: var(--bb-layout-sidebar-banner-background);
|
||||
height: var(--bb-layout-header-height);
|
||||
font-size: var(--bb-layout-banner-font-size);
|
||||
border-bottom: 1px solid var(--bb-layout-banner-border-color);
|
||||
|
||||
.layout-logo {
|
||||
width: var(--bb-layout-banner-logo-width);
|
||||
border-radius: var(--bs-border-radius);
|
||||
background-color: var(--bb-layout-logo-bg);
|
||||
border: 1px solid var(--bb-layout-logo-border-color);
|
||||
|
||||
+ .layout-title {
|
||||
margin-left: var(--bb-layout-title-margin-left);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.layout-user {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.layout-menu {
|
||||
overflow-x: hidden;
|
||||
padding: 0.5rem 0;
|
||||
height: calc(100vh - var(--bb-layout-header-height));
|
||||
|
||||
.menu {
|
||||
--bb-menu-item-hover-color: var(--bb-layout-header-color);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.has-sidebar {
|
||||
.layout-side {
|
||||
top: var(--bb-layout-header-height);
|
||||
|
||||
.layout-banner {
|
||||
display: none;
|
||||
}
|
||||
|
||||
&.is-fixed-header {
|
||||
z-index: 1020;
|
||||
}
|
||||
}
|
||||
|
||||
.layout-main {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
.layout-right {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
&.is-fixed {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
}
|
||||
|
||||
.layout-header {
|
||||
background-color: var(--bb-layout-header-background);
|
||||
height: var(--bb-layout-header-height);
|
||||
color: var(--bb-layout-header-color);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 0 1rem;
|
||||
position: sticky;
|
||||
z-index: 1035;
|
||||
border-bottom: 1px solid var(--bb-layout-header-border-color);
|
||||
|
||||
&.is-fixed {
|
||||
top: 0;
|
||||
}
|
||||
|
||||
.widget {
|
||||
--bb-widget-toggle-color: var(--bb-layout-header-color);
|
||||
|
||||
.progress {
|
||||
height: 7px;
|
||||
}
|
||||
}
|
||||
|
||||
.logout-avatar {
|
||||
border-radius: 50%;
|
||||
}
|
||||
|
||||
.dropdown-logout {
|
||||
--bb-logout-text-color: var(--bb-layout-header-color);
|
||||
--bb-logout-user-bg: var(--bb-layout-menu-user-banner-background);
|
||||
--bb-logout-menu-border-color: var(--bb-layout-menu-user-border-color);
|
||||
|
||||
.dropdown-user img {
|
||||
border-radius: 50%;
|
||||
}
|
||||
}
|
||||
.layout-banner {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.layout-menu {
|
||||
border-right: 1px solid var(--bs-border-color);
|
||||
|
||||
.menu {
|
||||
--bb-menu-item-hover-bg: var(--bb-layout-menu-item-hover-bg);
|
||||
}
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.layout-main {
|
||||
padding: 1rem;
|
||||
position: relative;
|
||||
min-height: calc(100vh - var(--bb-layout-header-height) - var(--bb-layout-footer-height));
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
.layout-menu {
|
||||
overflow-x: hidden;
|
||||
padding: 0.5rem 0;
|
||||
height: calc(100% - var(--bb-layout-header-height));
|
||||
|
||||
.menu {
|
||||
--bb-menu-item-hover-bg: var(--bb-layout-menu-item-hover-bg);
|
||||
--bb-menu-item-hover-color: var(--bb-layout-header-color);
|
||||
}
|
||||
}
|
||||
|
||||
.layout-side {
|
||||
background-color: var(--bb-layout-sidebar-background);
|
||||
color: var(--bb-layout-sidebar-color);
|
||||
transition: transform .3s linear;
|
||||
transform: translateX(-100%);
|
||||
position: absolute;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
z-index: 1036;
|
||||
}
|
||||
|
||||
.layout-main {
|
||||
padding: 1rem;
|
||||
position: relative;
|
||||
min-height: calc(100vh - var(--bb-layout-header-height) - var(--bb-layout-footer-height));
|
||||
flex: 1;
|
||||
|
||||
.tabs.tabs-border-card {
|
||||
box-shadow: none;
|
||||
}
|
||||
}
|
||||
|
||||
.layout-header {
|
||||
background-color: var(--bb-layout-header-background);
|
||||
height: var(--bb-layout-header-height);
|
||||
color: var(--bb-layout-header-color);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 0 1rem;
|
||||
position: sticky;
|
||||
z-index: 1035;
|
||||
border-bottom: 1px solid var(--bb-layout-header-border-color);
|
||||
|
||||
&.is-fixed {
|
||||
top: 0;
|
||||
}
|
||||
|
||||
.layout-footer {
|
||||
&.is-collapsed {
|
||||
display: none;
|
||||
.widget {
|
||||
--bb-widget-toggle-color: var(--bb-layout-header-color);
|
||||
|
||||
.progress {
|
||||
height: 7px;
|
||||
}
|
||||
}
|
||||
|
||||
.layout-footer {
|
||||
height: var(--bb-layout-footer-height);
|
||||
color: var(--bb-layout-footer-color);
|
||||
background-color: var(--bb-layout-footer-background);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 0 1rem;
|
||||
border-top: 1px solid var(--bs-border-color);
|
||||
.logout-avatar {
|
||||
border-radius: 50%;
|
||||
}
|
||||
|
||||
&.is-fixed {
|
||||
z-index: 1020;
|
||||
position: sticky;
|
||||
bottom: 0;
|
||||
.dropdown-logout {
|
||||
--bb-logout-text-color: var(--bb-layout-header-color);
|
||||
--bb-logout-user-bg: var(--bb-layout-menu-user-banner-background);
|
||||
--bb-logout-menu-border-color: var(--bb-layout-menu-user-border-color);
|
||||
|
||||
.dropdown-user img {
|
||||
border-radius: 50%;
|
||||
}
|
||||
}
|
||||
|
||||
.layout-header-bar {
|
||||
padding: var(--bb-layout-headerbar-padding);
|
||||
color: var(--bb-layout-headerbar-color);
|
||||
background-color: var(--bb-layout-headerbar-background);
|
||||
border: var(--bs-border-width) solid var(--bb-layout-headerbar-border-color);
|
||||
border-radius: var(--bs-border-radius);
|
||||
cursor: pointer;
|
||||
|
||||
.fa-bars {
|
||||
transition: transform .3s linear;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -209,137 +182,118 @@
|
||||
&:not(.has-footer) {
|
||||
--bb-layout-footer-height: 0px;
|
||||
}
|
||||
|
||||
&.is-collapsed {
|
||||
.fa-bars {
|
||||
transform: rotate(90deg);
|
||||
}
|
||||
|
||||
.layout-side {
|
||||
transform: translateX(0);
|
||||
}
|
||||
|
||||
.layout-right {
|
||||
overflow: hidden;
|
||||
height: 100vh;
|
||||
}
|
||||
|
||||
.layout-footer {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.has-sidebar {
|
||||
.layout-side {
|
||||
z-index: 1030;
|
||||
}
|
||||
|
||||
.layout-main {
|
||||
overflow: hidden;
|
||||
height: calc(100vh - var(--bb-layout-header-height));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.layout-footer {
|
||||
height: var(--bb-layout-footer-height);
|
||||
color: var(--bb-layout-footer-color);
|
||||
background-color: var(--bb-layout-footer-background);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 0 1rem;
|
||||
border-top: 1px solid var(--bs-border-color);
|
||||
|
||||
&.is-fixed {
|
||||
z-index: 1035;
|
||||
position: sticky;
|
||||
bottom: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.has-sidebar {
|
||||
flex-direction: row;
|
||||
display: flex;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.layout-side {
|
||||
position: relative;
|
||||
}
|
||||
@media(min-width: 768px) {
|
||||
.layout {
|
||||
.layout-side {
|
||||
position: relative;
|
||||
width: var(--bb-layout-sidebar-width);
|
||||
transform: translateX(0);
|
||||
transition: width .3s linear;
|
||||
|
||||
.layout-header-bar {
|
||||
padding: var(--bb-layout-headerbar-padding);
|
||||
color: var(--bb-layout-headerbar-color);
|
||||
background-color: var(--bb-layout-headerbar-background);
|
||||
border: var(--bs-border-width) solid var(--bb-layout-headerbar-border-color);
|
||||
border-radius: var(--bs-border-radius);
|
||||
.layout-menu {
|
||||
border-right: 1px solid var(--bs-border-color);
|
||||
}
|
||||
}
|
||||
|
||||
.fa-bars {
|
||||
transition: transform .3s linear;
|
||||
}
|
||||
.layout-right {
|
||||
display: flex;
|
||||
flex-flow: column;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
&.is-collapsed .fa-bars {
|
||||
transform: rotate(90deg);
|
||||
}
|
||||
}
|
||||
|
||||
.layout-banner-link {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
@media (min-width: 768px) {
|
||||
.layout.is-page .layout-side {
|
||||
transform: translateX(0);
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.layout.is-page .has-sidebar .layout-side {
|
||||
top: 0;
|
||||
}
|
||||
|
||||
.layout.is-page.has-sidebar .layout-side.is-fixed-header {
|
||||
top: 0;
|
||||
height: calc(100vh);
|
||||
}
|
||||
|
||||
.layout.is-page :not(.layout-right) .layout-main,
|
||||
.layout.is-page .layout-right {
|
||||
width: calc(100% - var(--bb-layout-sidebar-width));
|
||||
}
|
||||
|
||||
.layout.is-page .layout-side {
|
||||
width: var(--bb-layout-sidebar-width);
|
||||
}
|
||||
|
||||
.layout.is-page .layout-side.is-collapsed:not(:hover),
|
||||
.layout.is-page .layout-side:not(:hover) .menu.is-vertical.is-collapsed {
|
||||
width: var(--bb-layout-sidebar-collapse-width);
|
||||
}
|
||||
|
||||
.layout.is-page .layout-side.is-fixed-header {
|
||||
position: sticky;
|
||||
top: var(--bb-layout-header-height);
|
||||
height: calc(100vh - var(--bb-layout-header-height));
|
||||
}
|
||||
|
||||
.layout.is-page .layout-side.is-fixed-header.is-fixed-footer {
|
||||
height: calc(100vh - var(--bb-layout-header-height) - var(--bb-layout-footer-height));
|
||||
}
|
||||
|
||||
.layout.is-page .layout-side .layout-menu {
|
||||
height: auto;
|
||||
}
|
||||
|
||||
.layout .layout-side,
|
||||
.layout.is-page .layout-side,
|
||||
.layout .menu.is-vertical {
|
||||
transition: width .3s linear;
|
||||
}
|
||||
|
||||
.layout-right {
|
||||
display: flex;
|
||||
flex-flow: column;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.layout.is-page .layout-footer.is-fixed,
|
||||
.layout.is-page .layout-header.is-fixed,
|
||||
.layout.is-page .layout-side.is-fixed-header {
|
||||
z-index: 1025;
|
||||
}
|
||||
|
||||
.layout.is-page .layout-title {
|
||||
display: inline-block;
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
flex: 1 1 auto;
|
||||
opacity: 1;
|
||||
transition: opacity .3s linear;
|
||||
color: var(--bb-layout-title-color);
|
||||
}
|
||||
|
||||
.layout.is-page .is-collapsed .layout-title {
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
.layout.is-page.has-sidebar .layout-side {
|
||||
min-height: calc(100vh);
|
||||
}
|
||||
|
||||
.layout.is-page .has-sidebar .layout-side {
|
||||
min-height: calc(100vh - var(--bb-layout-header-height) - var(--bb-layout-footer-height));
|
||||
}
|
||||
|
||||
.layout.is-page.has-sidebar .layout-side.is-fixed-header.is-fixed-footer .layout-menu,
|
||||
.layout.is-page .layout-side.is-fixed-header .layout-menu {
|
||||
height: calc(100vh - var(--bb-layout-header-height));
|
||||
}
|
||||
|
||||
.layout.is-page .layout-side.is-fixed-header.is-fixed-footer .layout-menu {
|
||||
height: calc(100vh - var(--bb-layout-header-height) - var(--bb-layout-footer-height));
|
||||
}
|
||||
|
||||
.layout.is-page .layout-main.is-collapsed {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.layout.is-page .layout-footer.is-collapsed {
|
||||
display: flex;
|
||||
&.has-sidebar {
|
||||
.layout-side {
|
||||
&.is-fixed-header {
|
||||
position: sticky;
|
||||
top: 0;
|
||||
height: 100vh;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&.is-collapsed {
|
||||
.layout-side {
|
||||
&:not(:hover) {
|
||||
--bb-layout-sidebar-width: var(--bb-layout-sidebar-collapse-width);
|
||||
|
||||
.menu.is-vertical {
|
||||
--bb-layout-sidebar-width: var(--bb-layout-sidebar-collapse-width);
|
||||
}
|
||||
}
|
||||
|
||||
&:hover {
|
||||
.layout-title,
|
||||
.menu.is-vertical .menu-text {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.layout-main {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.layout-footer {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.layout-title,
|
||||
.menu.is-vertical .menu-text {
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -89,9 +89,10 @@ public class LayoutTest : BootstrapBlazorTestBase
|
||||
pb.Add(a => a.IsCollapsedChanged, v => collapsed = v);
|
||||
});
|
||||
|
||||
var bar = cut.Find(".layout-header-bar");
|
||||
await cut.InvokeAsync(() =>
|
||||
{
|
||||
cut.Find("header > a").Click();
|
||||
bar.Click();
|
||||
});
|
||||
Assert.True(collapsed);
|
||||
|
||||
@ -99,19 +100,6 @@ public class LayoutTest : BootstrapBlazorTestBase
|
||||
cut.WaitForAssertion(() => Assert.DoesNotContain("<i class=\"fa-solid fa-bars\"></i>", cut.Markup));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void IsPage_OK()
|
||||
{
|
||||
var cut = Context.RenderComponent<Layout>(pb =>
|
||||
{
|
||||
pb.Add(a => a.IsPage, true);
|
||||
});
|
||||
Assert.Contains("is-page", cut.Markup);
|
||||
|
||||
cut.SetParametersAndRender(pb => pb.Add(a => a.IsPage, false));
|
||||
cut.WaitForAssertion(() => Assert.DoesNotContain("is-page", cut.Markup));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void IsFullSide_OK()
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user