Skip to content

Commit

Permalink
feat(Icon): add BootstrapBlazorIcon component (#3724)
Browse files Browse the repository at this point in the history
* feat: 增加 Icon 组件库

* feat: 增加 Icon 图标

* doc: 增加示例

* refactor: 增加图标配置

* doc: 更新样式逻辑

* test: 增加单元测试

* chore: bump version 8.6.4
  • Loading branch information
ArgoZhang authored Jun 25, 2024
1 parent 77a7dbf commit baa2aef
Show file tree
Hide file tree
Showing 14 changed files with 202 additions and 2 deletions.
26 changes: 26 additions & 0 deletions src/BootstrapBlazor.Server/Components/Samples/Icons.razor
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
@page "/icon"
@inject IStringLocalizer<Icons> Localizer

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

<h4>@Localizer["IconsDescription"]</h4>

<DemoBlock Title="@Localizer["FATitle"]" Introduction="@Localizer["FAIntro"]" Name="Font">
<div class="bb-icon-list">
<BootstrapBlazorIcon Name="fa-solid fa-home"></BootstrapBlazorIcon>
</div>
</DemoBlock>

<DemoBlock Title="@Localizer["SvgTitle"]" Introduction="@Localizer["SvgIntro"]" Name="Svg">
<div class="bb-icon-list">
<BootstrapBlazorIcon Name="config" IsSvgSprites="true" Url="./_content/BootstrapBlazor.IconPark/icon-park.svg"></BootstrapBlazorIcon>
</div>
</DemoBlock>

<DemoBlock Title="@Localizer["ImageTitle"]" Introduction="@Localizer["ImageIntro"]" Name="Image">
<div class="bb-icon-list">
<BootstrapBlazorIcon>
<img src="./favicon.png" alt="img" />
</BootstrapBlazorIcon>
</div>
</DemoBlock>
13 changes: 13 additions & 0 deletions src/BootstrapBlazor.Server/Components/Samples/Icons.razor.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
// Copyright (c) Argo Zhang ([email protected]). All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
// Website: https://www.blazor.zone or https://argozhang.github.io/

namespace BootstrapBlazor.Server.Components.Samples;

/// <summary>
/// Icon 组件
/// </summary>
public partial class Icons : ComponentBase
{

}
8 changes: 8 additions & 0 deletions src/BootstrapBlazor.Server/Components/Samples/Icons.razor.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
.bb-icon-list {
display: flex;
}

::deep .bb-icon {
--bb-icon-width: 24px;
--bb-icon-color: var(--bs-body-color);
}
Original file line number Diff line number Diff line change
Expand Up @@ -630,6 +630,11 @@ void AddData(DemoMenuItem item)
Url = "handwritten"
},
new()
{
Text = Localizer["Icon"],
Url = "icon"
},
new()
{
Text = Localizer["IconPark"],
Url = "icon-park"
Expand Down
11 changes: 11 additions & 0 deletions src/BootstrapBlazor.Server/Locales/en-US.json
Original file line number Diff line number Diff line change
Expand Up @@ -4524,6 +4524,7 @@
"ListView": "ListView",
"ListGroup": "ListGroup",
"Locator": "IpLocatorFactory",
"Icon": "Icon",
"ImageViewer": "ImageViewer",
"FileIcon": "FileIcon",
"Popover": "Popover",
Expand Down Expand Up @@ -6483,5 +6484,15 @@
"NormalTitle": "Icon",
"NormalIntro": "Use the <code>BootstrapBlazorSvgIcon</code> component to set its <code>Name</code> parameter.",
"NormalDesc": "For more icon names, please visit ByteDance official website <a href=\"https://iconpark.oceanengine.com/official\" target=\"_blank\">https://iconpark.oceanengine.com/official</a>"
},
"BootstrapBlazor.Server.Components.Samples.Icons": {
"IconsTitle": "Icon",
"IconsDescription": "Supports font icons, vector SVG icons, and Image pictures",
"FATitle": "Font Icons",
"FAIntro": "You can specify the icon style by setting <code>Name</code>",
"SvgTitle": "Svg Icons",
"SvgIntro": "Load the <code>Svg</code> sprite image by setting <code>IsSvgSprites=\"true\"</code> <code>Url</code> and specify its <code>Id</code> value by <code>Name</code>",
"ImageTitle": "Image",
"ImageIntro": "Customize the displayed content through the <code>ChildContent</code> template"
}
}
11 changes: 11 additions & 0 deletions src/BootstrapBlazor.Server/Locales/zh-CN.json
Original file line number Diff line number Diff line change
Expand Up @@ -4524,6 +4524,7 @@
"ListView": "列表组件 ListView",
"ListGroup": "列表框 ListGroup",
"Locator": "位置定位 IpLocatorFactory",
"Icon": "图标 Icon",
"ImageViewer": "图片 ImageViewer",
"FileIcon": "文件图标 FileIcon",
"Popover": "弹出窗 Popover",
Expand Down Expand Up @@ -6483,5 +6484,15 @@
"NormalTitle": "图标组件",
"NormalIntro": "使用 <code>BootstrapBlazorSvgIcon</code> 组件设置其 <code>Name</code> 参数即可",
"NormalDesc": "更多图标名称请访问字节跳动官网 <a href=\"https://iconpark.oceanengine.com/official\" target=\"_blank\">https://iconpark.oceanengine.com/official</a>"
},
"BootstrapBlazor.Server.Components.Samples.Icons": {
"IconsTitle": "Icon 图标",
"IconsDescription": "同时支持字体图标、矢量 Svg 图标、以及 Image 图片",
"FATitle": "字体图标",
"FAIntro": "通过设置 <code>Name</code> 指定图标样式即可",
"SvgTitle": "矢量图标",
"SvgIntro": "通过设置 <code>IsSvgSprites=\"true\"</code> <code>Url</code> 加载 <code>Svg</code> 雪碧图,通过 <code>Name</code> 指定其 <code>Id</code> 值",
"ImageTitle": "图片",
"ImageIntro": "通过 <code>ChildContent</code> 模板自定义显示内容"
}
}
1 change: 1 addition & 0 deletions src/BootstrapBlazor.Server/docs.json
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@
"live2d-display": "Live2DDisplays",
"locator": "Locators",
"logout": "Logouts",
"icon": "Icons",
"icon-park": "IconParks",
"image-viewer": "ImageViewers",
"input-number": "InputNumbers",
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.6.3</Version>
<Version>8.6.4</Version>
</PropertyGroup>

<ItemGroup Condition="'$(TargetFramework)' == 'net5.0'">
Expand Down
19 changes: 19 additions & 0 deletions src/BootstrapBlazor/Components/Icon/BootstrapBlazorIcon.razor
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
@namespace BootstrapBlazor.Components
@inherits BootstrapComponentBase

<div @attributes="@AdditionalAttributes" class="@ClassString">
@if (ChildContent != null)
{
@ChildContent
}
else if (IsSvgSprites)
{
<svg xmlns="http://www.w3.org/2000/svg">
<use href="@Href"></use>
</svg>
}
else
{
<i class="@Name"></i>
}
</div>
43 changes: 43 additions & 0 deletions src/BootstrapBlazor/Components/Icon/BootstrapBlazorIcon.razor.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
// Copyright (c) Argo Zhang ([email protected]). All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
// Website: https://www.blazor.zone or https://argozhang.github.io/

namespace BootstrapBlazor.Components;

/// <summary>
/// Icon 组件
/// </summary>
public partial class BootstrapBlazorIcon
{
/// <summary>
/// 获得/设置 图标名称
/// </summary>
/// <remarks>如果是字库图标应该是样式名称如 fa-solid fa-home 如果是 svg sprites 应该为 Id</remarks>
[Parameter]
[NotNull]
public string? Name { get; set; }

/// <summary>
/// 获得/设置 是否为 svg sprites 默认 false
/// </summary>
[Parameter]
public bool IsSvgSprites { get; set; }

/// <summary>
/// 获得/设置 Svg Sprites 路径
/// </summary>
[Parameter]
public string? Url { get; set; }

/// <summary>
/// 获得/设置 子组件
/// </summary>
[Parameter]
public RenderFragment? ChildContent { get; set; }

private string? Href => $"{Url}#{Name}";

private string? ClassString => CssBuilder.Default("bb-icon")
.AddClass($"bb-icon-{Name}", !string.IsNullOrEmpty(Name) && IsSvgSprites)
.Build();
}
22 changes: 22 additions & 0 deletions src/BootstrapBlazor/Components/Icon/BootstrapBlazorIcon.razor.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
.bb-icon {
--bb-icon-width: 12px;
--bb-icon-color: var(--bs-body-color);
display: inline-flex;

> svg {
width: var(--bb-icon-width);
height: var(--bb-icon-width);

> * {
stroke: var(--bb-icon-color);
}
}

> i {
font-size: var(--bb-icon-width);
}

> img {
width: var(--bb-icon-width);
}
}
1 change: 1 addition & 0 deletions src/BootstrapBlazor/wwwroot/scss/components.scss
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@
@import "../../Components/GoTop/GoTop.razor.scss";
@import "../../Components/GroupBox/GroupBox.razor.scss";
@import "../../Components/Handwritten/Handwritten.razor.scss";
@import "../../Components/Icon/BootstrapBlazorIcon.razor.scss";
@import "../../Components/IFrame/IFrame.razor.scss";
@import "../../Components/ImagePreviewer/ImagePreviewer.razor.scss";
@import "../../Components/ImageViewer/ImageViewer.razor.scss";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ public partial class SvgIcon
/// 获得 样式字符串
/// </summary>
private string? ClassString => CssBuilder.Default("bb-svg-icon")
.AddClass($"bb-svg-icon-{Name}")
.AddClass($"bb-svg-icon-{Name}", !string.IsNullOrEmpty(Name))
.Build();

/// <summary>
Expand Down
40 changes: 40 additions & 0 deletions test/UnitTest/Components/IconTest.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
// Copyright (c) Argo Zhang ([email protected]). All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
// Website: https://www.blazor.zone or https://argozhang.github.io/

namespace UnitTest.Components;

public class IconTest : BootstrapBlazorTestBase
{
[Fact]
public void FontIcon_Ok()
{
var cut = Context.RenderComponent<BootstrapBlazorIcon>(pb =>
{
pb.Add(a => a.Name, "fa-solid fa-home");
});
cut.Contains("i class=\"fa-solid fa-home\"");
}

[Fact]
public void SvgIcon_Ok()
{
var cut = Context.RenderComponent<BootstrapBlazorIcon>(pb =>
{
pb.Add(a => a.Name, "home");
pb.Add(a => a.IsSvgSprites, true);
pb.Add(a => a.Url, "./_content/svg.svg");
});
cut.Contains("<use href=\"./_content/svg.svg#home\"></use>");
}

[Fact]
public void ImageIcon_Ok()
{
var cut = Context.RenderComponent<BootstrapBlazorIcon>(pb =>
{
pb.Add(a => a.ChildContent, builder => builder.AddMarkupContent(0, "<img src=\"test.png\" />"));
});
cut.Contains("<img src=\"test.png\" />");
}
}

0 comments on commit baa2aef

Please sign in to comment.