diff --git a/src/BootstrapBlazor.Server/Components/Samples/Navbars.razor b/src/BootstrapBlazor.Server/Components/Samples/Navbars.razor new file mode 100644 index 00000000000..f4ed79e64cd --- /dev/null +++ b/src/BootstrapBlazor.Server/Components/Samples/Navbars.razor @@ -0,0 +1,77 @@ +@page "/navbar" +@inject IStringLocalizer Localizer + +

@Localizer["NavbarTitle"]

+ +

@Localizer["NavbarDescription"]

+ + + + + Navbar + + + + + Home + + + + Action + + + Another action + + + + Something else here + + + Disabled + + About + + + + + + + + + + +
+

Nav

+
    +
  • Size: 指定导航栏响应阈值,默认 Size.Medium
  • +
  • BackgroundColorCssClass: 导航栏背景色样式,默认 null 未设置使用 bg-body-tertiary
  • +
+

NavbarBrand

+

渲染 navbar-brand 样式,导航栏 Brand 当屏幕宽度小于特定阈值时导航栏会响应式收起,NavbarBrand 的内容始终显示

+

NavbarToggleButton

+

渲染 navbar-toggler 样式,导航栏中的折叠展开按钮,当屏幕宽度小于特定阈值时显示,通过设置参数 Target 值指定折叠展开组件 NavbarCollapse

+

NavbarCollapse

+

渲染 collapse navbar-collapse 样式,导航栏中的可折叠展开区域,通过设置参数 Id 值,与组件 NavbarToggleButton 联动

+

NavbarGroup

+

渲染 navbar-nav 样式,导航栏中区域分组容器组件

+
    +
  • IsScrolling: 是否开启滚动条
  • +
  • Height: 组件高度,默认 200px
  • +
+

NavbarItem

+

渲染 navbar-item 样式,导航栏中单项容器组件,通过内置自定义组件或者 Html 实现导航项

+

NavbarLink

+

渲染 nav-link 样式,导航栏中导航组件,内部渲染为 a 链接

+
    +
  • Url: 导航地址
  • +
  • Target: 导航目标
  • +
  • ImageUrl: 图片地址
  • +
  • ImageCss: 图片样式
  • +
+

NavbarDropdown

+

渲染 nav-item dropdown 样式,导航栏中下拉菜单组件

+

NavbarDropdownItem

+

渲染 dropdown-item 样式,导航栏中下拉菜单组件内项目

+
+
diff --git a/src/BootstrapBlazor.Server/Components/Samples/Navbars.razor.cs b/src/BootstrapBlazor.Server/Components/Samples/Navbars.razor.cs new file mode 100644 index 00000000000..6cad933b4ec --- /dev/null +++ b/src/BootstrapBlazor.Server/Components/Samples/Navbars.razor.cs @@ -0,0 +1,41 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the Apache 2.0 License +// 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.Components.Forms; + +namespace BootstrapBlazor.Server.Components.Samples; + +/// +/// Navbar 示例 +/// +public partial class Navbars +{ + private List _dropdownItems = []; + private SearchModel _searchModel = new SearchModel(); + + /// + /// + /// + protected override void OnInitialized() + { + base.OnInitialized(); + + _dropdownItems.AddRange([ + new SelectedItem() { Text="Item1", Value="0"}, + new SelectedItem() { Text="Item2", Value="1"}, + new SelectedItem() { Text="Item3", Value="2"} + ]); + } + + private Task OnValidSubmit(EditContext context) + { + return Task.CompletedTask; + } + + class SearchModel + { + public string? SearchText { get; set; } + } +} diff --git a/src/BootstrapBlazor.Server/Extensions/MenusLocalizerExtensions.cs b/src/BootstrapBlazor.Server/Extensions/MenusLocalizerExtensions.cs index 4c5e2a72358..6257ea71252 100644 --- a/src/BootstrapBlazor.Server/Extensions/MenusLocalizerExtensions.cs +++ b/src/BootstrapBlazor.Server/Extensions/MenusLocalizerExtensions.cs @@ -1458,6 +1458,12 @@ void AddLayout(DemoMenuItem item) Url = "footer" }, new() + { + IsNew = true, + Text = Localizer["Navbar"], + Url = "navbar" + }, + new() { Text = Localizer["Row"], Url = "row" diff --git a/src/BootstrapBlazor.Server/Locales/en-US.json b/src/BootstrapBlazor.Server/Locales/en-US.json index d21150eac41..ff02ed9722e 100644 --- a/src/BootstrapBlazor.Server/Locales/en-US.json +++ b/src/BootstrapBlazor.Server/Locales/en-US.json @@ -4847,7 +4847,8 @@ "SocketDataEntity": "DataEntity", "NetworkMonitor": "Network Monitor", "Toolbar": "Toolbar", - "OpcDaService": "OpcDaServer" + "OpcDaService": "OpcDaServer", + "Navbar": "Navbar" }, "BootstrapBlazor.Server.Components.Samples.Table.TablesHeader": { "TablesHeaderTitle": "Header grouping function", @@ -7165,5 +7166,11 @@ "OpcDaDescription": "Connect to OpcDa Server to obtain PLC real-time data", "OpcDaNormalTitle": "Basic usage", "OpcDaNormalIntro": "Get an instance by injecting the service IOpcDaServer and call the Read method to get the PLC Tag value." + }, + "BootstrapBlazor.Server.Components.Samples.Navbars": { + "NavbarTitle": "Navbar", + "NavbarDescription": "A powerful, responsive navigation header, the navbar. Includes support for branding, navigation, and more", + "NormalTitle": "Basic usage", + "NormalIntro": "By setting NavbarBrand NavbarToggleButton NavbarCollapse NavbarGroup NavbarItem to layout its internal elements" } } diff --git a/src/BootstrapBlazor.Server/Locales/zh-CN.json b/src/BootstrapBlazor.Server/Locales/zh-CN.json index 3cea5bb4290..aaabe294bf2 100644 --- a/src/BootstrapBlazor.Server/Locales/zh-CN.json +++ b/src/BootstrapBlazor.Server/Locales/zh-CN.json @@ -4847,7 +4847,8 @@ "SocketDataEntity": "通讯数据转实体类", "NetworkMonitor": "网络状态 NetworkMonitor", "Toolbar": "工具栏 Toolbar", - "OpcDaService": "OpcDaServer 服务" + "OpcDaService": "OpcDaServer 服务", + "Navbar": "导航栏 Navbar" }, "BootstrapBlazor.Server.Components.Samples.Table.TablesHeader": { "TablesHeaderTitle": "表头分组功能", @@ -7165,5 +7166,11 @@ "OpcDaDescription": "连接 OpcDa Server 获得 PLC 实时数据", "OpcDaNormalTitle": "基本用法", "OpcDaNormalIntro": "通过注入服务 IOpcDaServer 获得实例,调用 Read 方法获得 PLC 位号值" + }, + "BootstrapBlazor.Server.Components.Samples.Navbars": { + "NavbarTitle": "Navbar 导航栏", + "NavbarDescription": "是网站开发中用于定义顶部导航区域或主页快速启动区域的结构化组件", + "NormalTitle": "基本用法", + "NormalIntro": "通过设置 NavbarBrand NavbarToggleButton NavbarCollapse NavbarGroup NavbarItem 对其内部元素布局" } } diff --git a/src/BootstrapBlazor.Server/docs.json b/src/BootstrapBlazor.Server/docs.json index 6b65fd874dc..92636c3bb40 100644 --- a/src/BootstrapBlazor.Server/docs.json +++ b/src/BootstrapBlazor.Server/docs.json @@ -250,7 +250,8 @@ "socket/data-entity": "Sockets\\DataEntities", "network-monitor": "NetworkMonitors", "toolbar": "Toolbars", - "opc-da": "OpcDa" + "opc-da": "OpcDa", + "navbar": "Navbars" }, "video": { "table": "BV1ap4y1x7Qn?p=1", diff --git a/src/BootstrapBlazor.Server/wwwroot/css/site.css b/src/BootstrapBlazor.Server/wwwroot/css/site.css index 8a26f0039b2..9672ae82968 100644 --- a/src/BootstrapBlazor.Server/wwwroot/css/site.css +++ b/src/BootstrapBlazor.Server/wwwroot/css/site.css @@ -52,7 +52,7 @@ html .search-dialog-mask { --bb-global-search-main-max-height: calc(100vh - 310px); } -.navbar { +.navbar-header { --bs-navbar-color: rgba(255,255,255,.85); --bs-navbar-hover-color: rgb(255,255,255); } diff --git a/src/BootstrapBlazor/Components/Dropdown/Dropdown.razor.scss b/src/BootstrapBlazor/Components/Dropdown/Dropdown.razor.scss index 20a30229440..daa6bf9ac34 100644 --- a/src/BootstrapBlazor/Components/Dropdown/Dropdown.razor.scss +++ b/src/BootstrapBlazor/Components/Dropdown/Dropdown.razor.scss @@ -1,3 +1,9 @@ [data-bs-theme='dark'] .dropdown-menu { --bs-dropdown-bg: #{$bs-dropdown-bg-dark}; } + +.dropdown-item { + > i + span { + margin-inline-start: 0.25rem; + } +} diff --git a/src/BootstrapBlazor/Components/Navbar/Navbar.razor b/src/BootstrapBlazor/Components/Navbar/Navbar.razor new file mode 100644 index 00000000000..a5258b46909 --- /dev/null +++ b/src/BootstrapBlazor/Components/Navbar/Navbar.razor @@ -0,0 +1,8 @@ +@namespace BootstrapBlazor.Components +@inherits BootstrapComponentBase + + diff --git a/src/BootstrapBlazor/Components/Navbar/Navbar.razor.cs b/src/BootstrapBlazor/Components/Navbar/Navbar.razor.cs new file mode 100644 index 00000000000..ba60ee368a7 --- /dev/null +++ b/src/BootstrapBlazor/Components/Navbar/Navbar.razor.cs @@ -0,0 +1,42 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the Apache 2.0 License +// See the LICENSE file in the project root for more information. +// Maintainer: Argo Zhang(argo@live.ca) Website: https://www.blazor.zone + +namespace BootstrapBlazor.Components; + +/// +/// Navbar 组件 +/// +public partial class Navbar +{ + /// + /// 获得/设置 组件大小 默认 + /// + [Parameter] + public Size Size { get; set; } = Size.Medium; + + /// + /// 获得/设置 背景色样式名称 默认 null 未设置 + /// + [Parameter] + public string? BackgroundColorCssClass { get; set; } + + /// + /// 获得/设置 子组件模板 + /// + [Parameter] + public RenderFragment? ChildContent { get; set; } + + /// + /// 获得 组件样式 + /// + private string? ClassString => CssBuilder.Default("navbar") + .AddClass($"navbar-expand", Size == Size.None) + .AddClass($"navbar-expand-{Size.ToDescriptionString()}", Size != Size.None) + .AddClass(BackgroundColorCssClass) + .AddClass("bg-body-tertiary", string.IsNullOrEmpty(BackgroundColorCssClass)) + .AddClassFromAttributes(AdditionalAttributes) + .Build(); +} + diff --git a/src/BootstrapBlazor/Components/Navbar/Navbar.razor.scss b/src/BootstrapBlazor/Components/Navbar/Navbar.razor.scss new file mode 100644 index 00000000000..7c3244bef06 --- /dev/null +++ b/src/BootstrapBlazor/Components/Navbar/Navbar.razor.scss @@ -0,0 +1,108 @@ +.navbar { + --bs-navbar-toggler-focus-width: 1px; +} + +.nav-link:focus-visible { + box-shadow: none; +} + +.navbar-nav { + --bs-nav-link-padding-x: .5rem; + margin-block-start: .5rem; +} + +.navbar-nav:not(:last-child) { + margin-block-end: .5rem; +} + +.navbar-expand { + .navbar-nav:last-child { + margin-block-start: 0; + margin-inline-start: .5rem; + } +} + +@media (min-width: 576px) { + .navbar-expand-sm { + .navbar-nav { + margin-block-start: 0; + margin-block-end: 0; + } + + .navbar-nav:last-child { + margin-inline-start: .5rem; + } + + .navbar-nav:not(:last-child) { + margin-inline-end: auto; + } + } +} + +@media (min-width: 768px) { + .navbar-expand-md { + .navbar-nav { + margin-block-start: 0; + margin-block-end: 0; + } + + .navbar-nav:last-child { + margin-inline-start: .5rem; + } + + .navbar-nav:not(:last-child) { + margin-inline-end: auto; + } + } +} + +@media (min-width: 992px) { + .navbar-expand-lg { + .navbar-nav { + margin-block-start: 0; + margin-block-end: 0; + } + + .navbar-nav:last-child { + margin-inline-start: .5rem; + } + + .navbar-nav:not(:last-child) { + margin-inline-end: auto; + } + } +} + +@media (min-width: 1200px) { + .navbar-expand-xl { + .navbar-nav { + margin-block-start: 0; + margin-block-end: 0; + } + + .navbar-nav:last-child { + margin-inline-start: .5rem; + } + + .navbar-nav:not(:last-child) { + margin-inline-end: auto; + } + } +} + +@media (min-width: 1400px) { + .navbar-expand-xxl { + .navbar-nav { + margin-block-start: 0; + margin-block-end: 0; + } + + .navbar-nav:last-child { + margin-inline-start: .5rem; + } + + .navbar-nav:not(:last-child) { + margin-inline-end: auto; + } + } +} diff --git a/src/BootstrapBlazor/Components/Navbar/NavbarBrand.razor b/src/BootstrapBlazor/Components/Navbar/NavbarBrand.razor new file mode 100644 index 00000000000..529836ec984 --- /dev/null +++ b/src/BootstrapBlazor/Components/Navbar/NavbarBrand.razor @@ -0,0 +1,6 @@ +@namespace BootstrapBlazor.Components +@inherits BootstrapComponentBase + +
+ @ChildContent +
diff --git a/src/BootstrapBlazor/Components/Navbar/NavbarBrand.razor.cs b/src/BootstrapBlazor/Components/Navbar/NavbarBrand.razor.cs new file mode 100644 index 00000000000..8428b8f2242 --- /dev/null +++ b/src/BootstrapBlazor/Components/Navbar/NavbarBrand.razor.cs @@ -0,0 +1,22 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the Apache 2.0 License +// See the LICENSE file in the project root for more information. +// Maintainer: Argo Zhang(argo@live.ca) Website: https://www.blazor.zone + +namespace BootstrapBlazor.Components; + +/// +/// NavBrand 组件 +/// +public partial class NavbarBrand +{ + /// + /// 获得/设置 子组件模板 + /// + [Parameter] + public RenderFragment? ChildContent { get; set; } + + private string? ClassString => CssBuilder.Default("navbar-brand") + .AddClassFromAttributes(AdditionalAttributes) + .Build(); +} diff --git a/src/BootstrapBlazor/Components/Navbar/NavbarCollapse.razor b/src/BootstrapBlazor/Components/Navbar/NavbarCollapse.razor new file mode 100644 index 00000000000..deed7046e66 --- /dev/null +++ b/src/BootstrapBlazor/Components/Navbar/NavbarCollapse.razor @@ -0,0 +1,6 @@ +@namespace BootstrapBlazor.Components +@inherits IdComponentBase + +
+ @ChildContent +
diff --git a/src/BootstrapBlazor/Components/Navbar/NavbarCollapse.razor.cs b/src/BootstrapBlazor/Components/Navbar/NavbarCollapse.razor.cs new file mode 100644 index 00000000000..09d37d38d3e --- /dev/null +++ b/src/BootstrapBlazor/Components/Navbar/NavbarCollapse.razor.cs @@ -0,0 +1,22 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the Apache 2.0 License +// See the LICENSE file in the project root for more information. +// Maintainer: Argo Zhang(argo@live.ca) Website: https://www.blazor.zone + +namespace BootstrapBlazor.Components; + +/// +/// NavbarCollapse 组件用于在导航栏中适配响应式布局 +/// +public partial class NavbarCollapse +{ + /// + /// 获得/设置 子组件模板 + /// + [Parameter] + public RenderFragment? ChildContent { get; set; } + + private string? ClassString => CssBuilder.Default("collapse navbar-collapse") + .AddClassFromAttributes(AdditionalAttributes) + .Build(); +} diff --git a/src/BootstrapBlazor/Components/Navbar/NavbarDropdown.razor b/src/BootstrapBlazor/Components/Navbar/NavbarDropdown.razor new file mode 100644 index 00000000000..eaac691d4bc --- /dev/null +++ b/src/BootstrapBlazor/Components/Navbar/NavbarDropdown.razor @@ -0,0 +1,11 @@ +@namespace BootstrapBlazor.Components +@inherits BootstrapComponentBase + +
+ +
    + @ChildContent +
+
diff --git a/src/BootstrapBlazor/Components/Navbar/NavbarDropdown.razor.cs b/src/BootstrapBlazor/Components/Navbar/NavbarDropdown.razor.cs new file mode 100644 index 00000000000..70f6880167d --- /dev/null +++ b/src/BootstrapBlazor/Components/Navbar/NavbarDropdown.razor.cs @@ -0,0 +1,48 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the Apache 2.0 License +// See the LICENSE file in the project root for more information. +// Maintainer: Argo Zhang(argo@live.ca) Website: https://www.blazor.zone + +namespace BootstrapBlazor.Components; + +/// +/// NavbarDropdown 组件用于在导航栏中创建下拉菜单 +/// +public partial class NavbarDropdown +{ + /// + /// 获得/设置 子组件模板 + /// + [Parameter] + public RenderFragment? ChildContent { get; set; } + + /// + /// 获得/设置 Dropdown 菜单标题文本 + /// + [Parameter] + public string? Text { get; set; } + + /// + /// 获得/设置 获取菜单对齐方式 默认 none 未设置 + /// + [Parameter] + public Alignment MenuAlignment { get; set; } + + /// + /// 获得/设置 下拉选项方向 默认 Dropdown 向下 + /// + [Parameter] + public Direction Direction { get; set; } + + private string? ClassString => CssBuilder.Default("nav-item") + .AddClass(Direction.ToDescriptionString()) + .AddClassFromAttributes(AdditionalAttributes) + .Build(); + + /// + /// 菜单对齐方式样式 + /// + private string? MenuAlignmentClass => CssBuilder.Default("dropdown-menu shadow") + .AddClass($"dropdown-menu-{MenuAlignment.ToDescriptionString()}", MenuAlignment == Alignment.Right) + .Build(); +} diff --git a/src/BootstrapBlazor/Components/Navbar/NavbarDropdownDivider.razor b/src/BootstrapBlazor/Components/Navbar/NavbarDropdownDivider.razor new file mode 100644 index 00000000000..a8bc1334f34 --- /dev/null +++ b/src/BootstrapBlazor/Components/Navbar/NavbarDropdownDivider.razor @@ -0,0 +1,4 @@ +@namespace BootstrapBlazor.Components +@inherits BootstrapComponentBase + +
  • diff --git a/src/BootstrapBlazor/Components/Navbar/NavbarDropdownItem.razor b/src/BootstrapBlazor/Components/Navbar/NavbarDropdownItem.razor new file mode 100644 index 00000000000..f705f496cbf --- /dev/null +++ b/src/BootstrapBlazor/Components/Navbar/NavbarDropdownItem.razor @@ -0,0 +1,8 @@ +@namespace BootstrapBlazor.Components +@inherits BootstrapComponentBase + +
  • + + @ChildContent + +
  • diff --git a/src/BootstrapBlazor/Components/Navbar/NavbarDropdownItem.razor.cs b/src/BootstrapBlazor/Components/Navbar/NavbarDropdownItem.razor.cs new file mode 100644 index 00000000000..61eb0944fac --- /dev/null +++ b/src/BootstrapBlazor/Components/Navbar/NavbarDropdownItem.razor.cs @@ -0,0 +1,30 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the Apache 2.0 License +// See the LICENSE file in the project root for more information. +// Maintainer: Argo Zhang(argo@live.ca) Website: https://www.blazor.zone + +namespace BootstrapBlazor.Components; + +/// +/// NavbarDropdownItem 组件用于在导航栏下拉菜单中创建菜单项 +/// +public partial class NavbarDropdownItem +{ + /// + /// 获得/设置 子组件模板 + /// + [Parameter] + public RenderFragment? ChildContent { get; set; } + + /// + /// 获得/设置 菜单项文本 + /// + [Parameter] + public string? Url { get; set; } + + /// + /// 获得/设置 A 标签 target 参数 默认 null + /// + [Parameter] + public string? Target { get; set; } +} diff --git a/src/BootstrapBlazor/Components/Navbar/NavbarGroup.razor b/src/BootstrapBlazor/Components/Navbar/NavbarGroup.razor new file mode 100644 index 00000000000..470a443dc9e --- /dev/null +++ b/src/BootstrapBlazor/Components/Navbar/NavbarGroup.razor @@ -0,0 +1,6 @@ +@namespace BootstrapBlazor.Components +@inherits BootstrapComponentBase + +
    + @ChildContent +
    diff --git a/src/BootstrapBlazor/Components/Navbar/NavbarGroup.razor.cs b/src/BootstrapBlazor/Components/Navbar/NavbarGroup.razor.cs new file mode 100644 index 00000000000..469a497b427 --- /dev/null +++ b/src/BootstrapBlazor/Components/Navbar/NavbarGroup.razor.cs @@ -0,0 +1,50 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the Apache 2.0 License +// See the LICENSE file in the project root for more information. +// Maintainer: Argo Zhang(argo@live.ca) Website: https://www.blazor.zone + +namespace BootstrapBlazor.Components; + +/// +/// NavbarGroup 组件用于在导航栏中分组 +/// +public partial class NavbarGroup +{ + /// + /// 获得/设置 子组件模板 + /// + [Parameter] + public RenderFragment? ChildContent { get; set; } + + /// + /// 获得/设置 是否启用滚动 + /// + [Parameter] + public bool IsScrolling { get; set; } + + /// + /// 获得/设置 高度值 默认 200px; + /// + [Parameter] + public string? Height { get; set; } + + private string? ClassString => CssBuilder.Default("navbar-nav") + .AddClass("navbar-nav-scroll", IsScrolling) + .AddClassFromAttributes(AdditionalAttributes) + .Build(); + + private string? StyleString => CssBuilder.Default() + .AddStyle("--bs-scroll-height", Height, IsScrolling) + .AddStyleFromAttributes(AdditionalAttributes) + .Build(); + + /// + /// + /// + protected override void OnParametersSet() + { + base.OnParametersSet(); + + Height ??= "200px"; + } +} diff --git a/src/BootstrapBlazor/Components/Navbar/NavbarItem.razor b/src/BootstrapBlazor/Components/Navbar/NavbarItem.razor new file mode 100644 index 00000000000..529836ec984 --- /dev/null +++ b/src/BootstrapBlazor/Components/Navbar/NavbarItem.razor @@ -0,0 +1,6 @@ +@namespace BootstrapBlazor.Components +@inherits BootstrapComponentBase + +
    + @ChildContent +
    diff --git a/src/BootstrapBlazor/Components/Navbar/NavbarItem.razor.cs b/src/BootstrapBlazor/Components/Navbar/NavbarItem.razor.cs new file mode 100644 index 00000000000..102f34842e4 --- /dev/null +++ b/src/BootstrapBlazor/Components/Navbar/NavbarItem.razor.cs @@ -0,0 +1,22 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the Apache 2.0 License +// See the LICENSE file in the project root for more information. +// Maintainer: Argo Zhang(argo@live.ca) Website: https://www.blazor.zone + +namespace BootstrapBlazor.Components; + +/// +/// NavbarItem 组件用于在导航栏中添加子组件 +/// +public partial class NavbarItem +{ + /// + /// 获得/设置 子组件模板 + /// + [Parameter] + public RenderFragment? ChildContent { get; set; } + + private string? ClassString => CssBuilder.Default("navbar-item") + .AddClassFromAttributes(AdditionalAttributes) + .Build(); +} diff --git a/src/BootstrapBlazor/Components/Navbar/NavbarLink.razor b/src/BootstrapBlazor/Components/Navbar/NavbarLink.razor new file mode 100644 index 00000000000..5e161dc1e62 --- /dev/null +++ b/src/BootstrapBlazor/Components/Navbar/NavbarLink.razor @@ -0,0 +1,24 @@ +@namespace BootstrapBlazor.Components +@inherits ButtonBase + + diff --git a/src/BootstrapBlazor/Components/Navbar/NavbarLink.razor.cs b/src/BootstrapBlazor/Components/Navbar/NavbarLink.razor.cs new file mode 100644 index 00000000000..ac5415f82d7 --- /dev/null +++ b/src/BootstrapBlazor/Components/Navbar/NavbarLink.razor.cs @@ -0,0 +1,59 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the Apache 2.0 License +// See the LICENSE file in the project root for more information. +// Maintainer: Argo Zhang(argo@live.ca) Website: https://www.blazor.zone + +namespace BootstrapBlazor.Components; + +/// +/// NavbarLink 组件用于在导航栏中添加链接 +/// +public partial class NavbarLink +{ + /// + /// 获得/设置 Url 默认为 # + /// + [Parameter] + public string? Url { get; set; } + + /// + /// 获得/设置 A 标签 target 参数 默认 null + /// + [Parameter] + public string? Target { get; set; } + + /// + /// 获得/设置 显示图片地址 默认为 null + /// + [Parameter] + public string? ImageUrl { get; set; } + + /// + /// The css class of img element default value null + /// + [Parameter] + public string? ImageCss { get; set; } + + private string? ClassString => CssBuilder.Default("nav-link") + .AddClass("disabled", IsDisabled) + .AddClassFromAttributes(AdditionalAttributes) + .Build(); + + private async Task OnClickButton() + { + if (IsAsync) + { + IsAsyncLoading = true; + IsDisabled = true; + } + + await HandlerClick(); + + // 恢复按钮 + if (IsAsync) + { + IsDisabled = IsKeepDisabled; + IsAsyncLoading = false; + } + } +} diff --git a/src/BootstrapBlazor/Components/Navbar/NavbarToggleButton.razor b/src/BootstrapBlazor/Components/Navbar/NavbarToggleButton.razor new file mode 100644 index 00000000000..c3b115ffbde --- /dev/null +++ b/src/BootstrapBlazor/Components/Navbar/NavbarToggleButton.razor @@ -0,0 +1,14 @@ +@namespace BootstrapBlazor.Components +@inherits BootstrapComponentBase + + diff --git a/src/BootstrapBlazor/Components/Navbar/NavbarToggleButton.razor.cs b/src/BootstrapBlazor/Components/Navbar/NavbarToggleButton.razor.cs new file mode 100644 index 00000000000..155ee401c80 --- /dev/null +++ b/src/BootstrapBlazor/Components/Navbar/NavbarToggleButton.razor.cs @@ -0,0 +1,28 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the Apache 2.0 License +// See the LICENSE file in the project root for more information. +// Maintainer: Argo Zhang(argo@live.ca) Website: https://www.blazor.zone + +namespace BootstrapBlazor.Components; + +/// +/// NavbarToggleButton 组件 +/// +public partial class NavbarToggleButton +{ + /// + /// 获得/设置 联动组件选择器 默认 null + /// + [Parameter] + public string? Target { get; set; } + + /// + /// 获得/设置 子组件模板 + /// + [Parameter] + public RenderFragment? ChildContent { get; set; } + + private string? ClassString => CssBuilder.Default("navbar-toggler") + .AddClassFromAttributes(AdditionalAttributes) + .Build(); +} diff --git a/src/BootstrapBlazor/wwwroot/scss/components.scss b/src/BootstrapBlazor/wwwroot/scss/components.scss index 301cf21d748..55ec7de8039 100644 --- a/src/BootstrapBlazor/wwwroot/scss/components.scss +++ b/src/BootstrapBlazor/wwwroot/scss/components.scss @@ -70,6 +70,7 @@ @import "../../Components/Menu/Menu.razor.scss"; @import "../../Components/Message/Message.razor.scss"; @import "../../Components/Modal/Modal.razor.scss"; +@import "../../Components/Navbar/Navbar.razor.scss"; @import "../../Components/NetworkMonitor/NetworkMonitorIndicator.razor.scss"; @import "../../Components/Pagination/Pagination.razor.scss"; @import "../../Components/Popover/Popover.razor.scss"; diff --git a/test/UnitTest/Components/NavbarTest.cs b/test/UnitTest/Components/NavbarTest.cs new file mode 100644 index 00000000000..e44ab9c196f --- /dev/null +++ b/test/UnitTest/Components/NavbarTest.cs @@ -0,0 +1,100 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the Apache 2.0 License +// See the LICENSE file in the project root for more information. +// Maintainer: Argo Zhang(argo@live.ca) Website: https://www.blazor.zone + +namespace UnitTest.Components; + +public class NavbarTest : BootstrapBlazorTestBase +{ + [Fact] + public void Navbar_OK() + { + var cut = Context.RenderComponent(pb => + { + pb.Add(s => s.Size, Size.Medium); + pb.Add(s => s.BackgroundColorCssClass, "bg-primary"); + pb.AddChildContent(pb => + { + pb.AddChildContent("NavbarBrand"); + }); + pb.AddChildContent(pb => + { + pb.Add(a => a.Target, "#testId"); + }); + pb.AddChildContent(pb => + { + pb.Add(a => a.Id, "testId"); + pb.AddChildContent(pb => + { + pb.Add(a => a.IsScrolling, true); + pb.AddChildContent(pb => + { + pb.AddChildContent("Home"); + }); + pb.AddChildContent(pb => + { + pb.Add(a => a.Url, "#"); + pb.Add(a => a.ImageUrl, "https://example.com/logo.png"); + pb.Add(a => a.ImageCss, "logo-class"); + pb.Add(a => a.Target, "_blank"); + pb.AddChildContent("HomeLink"); + }); + pb.AddChildContent(pb => + { + pb.Add(a => a.Direction, Direction.Dropup); + pb.Add(a => a.MenuAlignment, Alignment.Right); + pb.Add(a => a.Text, "Dropdown"); + pb.AddChildContent(pb => + { + pb.AddChildContent("Action"); + }); + pb.AddChildContent(); + pb.AddChildContent(pb => + { + pb.Add(a => a.Url, "#"); + pb.Add(a => a.Target, "_blank"); + }); + }); + }); + }); + }); + Assert.Contains("NavbarBrand", cut.Markup); + Assert.Contains("data-bs-target=\"#testId", cut.Markup); + Assert.Contains("collapse navbar-collapse", cut.Markup); + Assert.Contains("navbar-nav", cut.Markup); + Assert.Contains("Home", cut.Markup); + Assert.Contains("HomeLink", cut.Markup); + + var toggle = cut.FindComponent(); + Assert.NotNull(toggle); + + toggle.SetParametersAndRender(pb => + { + pb.AddChildContent("ToggleButton"); + }); + Assert.Contains("ToggleButton", cut.Markup); + } + + [Fact] + public async Task NavbarLink_Ok() + { + var cut = Context.RenderComponent(pb => + { + pb.Add(a => a.Icon, "fa-test"); + pb.Add(a => a.Text, "Home"); + pb.Add(a => a.IsAsync, true); + pb.Add(a => a.OnClick, async () => + { + await Task.Yield(); + }); + }); + + Assert.Contains("Home", cut.Markup); + + var link = cut.Find("a"); + Assert.NotNull(link); + + await cut.InvokeAsync(() => link.Click()); + } +}