Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions src/BootstrapBlazor/Components/AutoFill/AutoFill.razor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

using Microsoft.AspNetCore.Components.Web.Virtualization;
using Microsoft.Extensions.Localization;
using System.Globalization;

namespace BootstrapBlazor.Components;

Expand Down Expand Up @@ -150,8 +151,8 @@ public partial class AutoFill<TValue>
.AddClass($"text-danger", IsValid.HasValue && !IsValid.Value)
.Build();

private string? PlaceHolderStyleString => RowHeight != 50f
? CssBuilder.Default().AddStyle("height", $"{RowHeight}px").Build()
private string? PlaceHolderStyleString => Math.Abs(RowHeight - 50f) > 0.1f
? CssBuilder.Default().AddClass($"height: {RowHeight.ToString(CultureInfo.InvariantCulture)}px;").Build()
: null;

/// <summary>
Expand Down
12 changes: 6 additions & 6 deletions src/BootstrapBlazor/Components/Badge/ShieldBadge.razor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -69,12 +69,12 @@ public partial class ShieldBadge
.Build();

private string? StyleString => CssBuilder.Default()
.AddStyle("--bb-shield-badge-icon-color", IconColor, !string.IsNullOrEmpty(IconColor))
.AddStyle("--bb-shield-badge-label-color", LabelColor, !string.IsNullOrEmpty(LabelColor))
.AddStyle("--bb-shield-badge-label-bg", LabelBackgroundColor, !string.IsNullOrEmpty(LabelBackgroundColor))
.AddStyle("--bb-shield-badge-text-color", TextColor, !string.IsNullOrEmpty(TextColor))
.AddStyle("--bb-shield-badge-text-bg", TextBackgroundColor, !string.IsNullOrEmpty(TextBackgroundColor))
.AddStyle("--bb-shield-badge-radius", $"{Math.Max(0, Radius)}px", Radius != 3)
.AddClass($"--bb-shield-badge-icon-color: {IconColor};", !string.IsNullOrEmpty(IconColor))
.AddClass($"--bb-shield-badge-label-color: {LabelColor};", !string.IsNullOrEmpty(LabelColor))
.AddClass($"--bb-shield-badge-label-bg: {LabelBackgroundColor};", !string.IsNullOrEmpty(LabelBackgroundColor))
.AddClass($"--bb-shield-badge-text-color: {TextColor};", !string.IsNullOrEmpty(TextColor))
.AddClass($"--bb-shield-badge-text-bg: {TextBackgroundColor};", !string.IsNullOrEmpty(TextBackgroundColor))
.AddClass($"--bb-shield-badge-radius: {Math.Max(0, Radius)}px;", Radius != 3)
.Build();

private string? IconString => CssBuilder.Default("shield-badge-icon")
Expand Down
8 changes: 4 additions & 4 deletions src/BootstrapBlazor/Components/Captcha/Captcha.razor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,15 +20,15 @@ public partial class Captcha
/// 获得 组件宽度
/// </summary>
private string? StyleString => CssBuilder.Default()
.AddStyle("width", $"{Width + 42}px", Width > 0)
.AddClass($"width: {Width + 42}px;", Width > 0)
.Build();

/// <summary>
/// 获得 加载图片失败样式
/// </summary>
private string? FailedStyle => CssBuilder.Default()
.AddStyle("width", $"{Width}px", Width > 0)
.AddStyle("height", $"{Height}px", Height > 0)
.AddClass($"width: {Width}px;", Width > 0)
.AddClass($"height: {Height}px;", Height > 0)
.Build();

/// <summary>
Expand Down Expand Up @@ -219,7 +219,7 @@ private CaptchaOption GetCaptchaOption()
private static bool CalcStddev(List<int> trails)
{
var ret = false;
if (trails.Any())
if (trails.Count > 0)
{
var average = trails.Sum() * 1.0 / trails.Count;
var dev = trails.Select(t => t - average);
Expand Down
2 changes: 1 addition & 1 deletion src/BootstrapBlazor/Components/Card/Card.razor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@ public partial class Card
private IIconTheme? IconTheme { get; set; }

private string? HeaderStyleString => CssBuilder.Default()
.AddStyle("--bs-card-cap-padding-y", HeaderPaddingY)
.AddClass($"--bs-card-cap-padding-y: {HeaderPaddingY};", !string.IsNullOrEmpty(HeaderPaddingY))
.AddStyleFromAttributes(AdditionalAttributes)
.Build();

Expand Down
8 changes: 5 additions & 3 deletions src/BootstrapBlazor/Components/Drawer/Drawer.razor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ public partial class Drawer
.Build();

private string? StyleString => CssBuilder.Default()
.AddStyle("--bb-drawer-position", Position)
.AddClass($"--bb-drawer-position: {Position};")
.AddClass($"--bb-drawer-zindex: {ZIndex};", ZIndex.HasValue)
.AddStyleFromAttributes(AdditionalAttributes)
.Build();
Expand All @@ -28,10 +28,12 @@ public partial class Drawer
/// 获得 抽屉 Style 字符串
/// </summary>
private string? DrawerStyleString => CssBuilder.Default()
.AddStyle("--bb-drawer-width", Width, Placement != Placement.Top && Placement != Placement.Bottom)
.AddStyle("--bb-drawer-height", Height, Placement == Placement.Top || Placement == Placement.Bottom)
.AddClass($"--bb-drawer-width: {Width};", !string.IsNullOrEmpty(Width) && !IsVertical)
.AddClass($"--bb-drawer-height: {Height};", !string.IsNullOrEmpty(Height) && IsVertical)
.Build();

private bool IsVertical => Placement == Placement.Top || Placement == Placement.Bottom;

/// <summary>
/// 获得 抽屉样式
/// </summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ public partial class EditorForm<TModel> : IShowLabel
.Build();

private string? FormStyleString => CssBuilder.Default()
.AddStyle("--bb-row-label-width", $"{LabelWidth}px", LabelWidth.HasValue)
.AddClass($"--bb-row-label-width: {LabelWidth}px;", LabelWidth.HasValue)
.Build();

/// <summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ public partial class BootstrapLabel
.Build();

private string? StyleString => CssBuilder.Default()
.AddStyle($"--bb-row-label-width", $"{LabelWidth}px", LabelWidth.HasValue)
.AddClass($"--bb-row-label-width: {LabelWidth}px;", LabelWidth.HasValue)
.AddStyleFromAttributes(AdditionalAttributes)
.Build();

Expand Down
2 changes: 1 addition & 1 deletion src/BootstrapBlazor/Components/Logout/Logout.razor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ public partial class Logout
.Build();

private string? AvatarStyleString => CssBuilder.Default()
.AddStyle("--bb-logout-user-avatar-border-radius", AvatarRadius, !string.IsNullOrEmpty(AvatarRadius))
.AddClass($"--bb-logout-user-avatar-border-radius: {AvatarRadius};", !string.IsNullOrEmpty(AvatarRadius))
.Build();

/// <summary>
Expand Down
2 changes: 1 addition & 1 deletion src/BootstrapBlazor/Components/Navbar/NavbarGroup.razor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ public partial class NavbarGroup
.Build();

private string? StyleString => CssBuilder.Default()
.AddStyle("--bs-scroll-height", Height, IsScrolling)
.AddClass($"--bs-scroll-height: {Height};", !string.IsNullOrEmpty(Height))
.AddStyleFromAttributes(AdditionalAttributes)
.Build();

Expand Down
2 changes: 1 addition & 1 deletion src/BootstrapBlazor/Components/Toolbar/Toolbar.razor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ public partial class Toolbar
.Build();

private string? StyleString => CssBuilder.Default()
.AddStyle("flex-wrap", "wrap", IsWrap)
.AddClass("flex-wrap: wrap;", IsWrap)
.AddStyleFromAttributes(AdditionalAttributes)
.Build();
}
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@ public partial class ValidateForm
private string? ShowAllInvalidResultString => ShowAllInvalidResult ? "true" : null;

private string? StyleString => CssBuilder.Default()
.AddStyle("--bb-row-label-width", $"{LabelWidth}px", LabelWidth.HasValue)
.AddClass($"--bb-row-label-width: {LabelWidth}px;", LabelWidth.HasValue)
.Build();

/// <summary>
Expand Down
98 changes: 26 additions & 72 deletions src/BootstrapBlazor/Utils/CssBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,18 @@
// See the LICENSE file in the project root for more information.
// Maintainer: Argo Zhang([email protected]) Website: https://www.blazor.zone

using System.Globalization;
using System.Text;

namespace BootstrapBlazor.Components;

/// <summary>
/// Css 生成操作类
/// </summary>
public class CssBuilder
{
private readonly List<string> stringBuffer;
private readonly StringBuilder _builder = new();
private bool _hasConent;
Comment on lines +16 to +17
Copy link

Copilot AI Sep 28, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The field name _hasConent has a spelling error. It should be _hasContent.

Copilot uses AI. Check for mistakes.

/// <summary>
/// Creates a CssBuilder used to define conditional CSS classes used in a component.
Expand All @@ -26,8 +30,11 @@ public class CssBuilder
/// <param name="value"></param>
protected CssBuilder(string? value)
{
stringBuffer = [];
AddClass(value);
if (!string.IsNullOrEmpty(value))
{
_builder.Append(value);
_hasConent = true;
Copy link

Copilot AI Sep 28, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The field name _hasConent has a spelling error. It should be _hasContent.

Copilot uses AI. Check for mistakes.
}
}

/// <summary>
Expand All @@ -37,7 +44,18 @@ protected CssBuilder(string? value)
/// <returns>CssBuilder</returns>
public CssBuilder AddClass(string? value)
{
if (!string.IsNullOrEmpty(value)) stringBuffer.Add(value);
if (!string.IsNullOrEmpty(value))
{
if (_hasConent)
Copy link

Copilot AI Sep 28, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The field name _hasConent has a spelling error. It should be _hasContent.

Copilot uses AI. Check for mistakes.
{
_builder.Append(' ');
}
else
{
_hasConent = true;
Copy link

Copilot AI Sep 28, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The field name _hasConent has a spelling error. It should be _hasContent.

Copilot uses AI. Check for mistakes.
}
_builder.Append(value);
}
return this;
}

Expand Down Expand Up @@ -99,76 +117,12 @@ public CssBuilder AddClassFromAttributes(IDictionary<string, object>? additional
{
if (additionalAttributes != null && additionalAttributes.TryGetValue("class", out var c))
{
var classList = c?.ToString();
AddClass(classList);
var classString = Convert.ToString(c, CultureInfo.InvariantCulture);
AddClass(classString);
}
return this;
}

/// <summary>
/// Adds a raw string to the builder that will be concatenated with the next style or value added to the builder.
/// </summary>
/// <param name="key">style property name</param>
/// <param name="value">CSS style to conditionally add.</param>
/// <returns>CssBuilder</returns>
public CssBuilder AddStyle(string key, string? value)
{
if (!string.IsNullOrEmpty(value)) stringBuffer.Add($"{key}: {value};");
return this;
}

/// <summary>
/// Adds a conditional css Style to the builder with space separator.
/// </summary>
/// <param name="key">style property name</param>
/// <param name="value">CSS style to conditionally add.</param>
/// <param name="when">Condition in which the CSS style is added.</param>
/// <returns>CssBuilder</returns>
public CssBuilder AddStyle(string key, string? value, bool when = true) => when ? AddStyle(key, value) : this;

/// <summary>
/// Adds a conditional css Style to the builder with space separator.
/// </summary>
/// <param name="key">style property name</param>
/// <param name="value">CSS style to conditionally add.</param>
/// <param name="when">Condition in which the CSS Style is added.</param>
/// <returns>CssBuilder</returns>
public CssBuilder AddStyle(string key, string? value, Func<bool> when) => AddStyle(key, value, when());

/// <summary>
/// Adds a conditional css Style to the builder with space separator.
/// </summary>
/// <param name="key">style property name</param>
/// <param name="value">Function that returns a css Style to conditionally add.</param>
/// <param name="when">Condition in which the CSS Style is added.</param>
/// <returns>CssBuilder</returns>
public CssBuilder AddStyle(string key, Func<string?> value, bool when = true) => when ? AddStyle(key, value()) : this;

/// <summary>
/// Adds a conditional css Style to the builder with space separator.
/// </summary>
/// <param name="key">style property name</param>
/// <param name="value">Function that returns a css Style to conditionally add.</param>
/// <param name="when">Condition in which the CSS Style is added.</param>
/// <returns>CssBuilder</returns>
public CssBuilder AddStyle(string key, Func<string?> value, Func<bool> when) => AddStyle(key, value, when());

/// <summary>
/// Adds a conditional nested CssBuilder to the builder with space separator.
/// </summary>
/// <param name="builder">CSS Style to conditionally add.</param>
/// <param name="when">Condition in which the CSS Style is added.</param>
/// <returns>CssBuilder</returns>
public CssBuilder AddStyle(CssBuilder builder, bool when = true) => when ? AddClass(builder.Build()) : this;

/// <summary>
/// Adds a conditional CSS Class to the builder with space separator.
/// </summary>
/// <param name="builder">CSS Class to conditionally add.</param>
/// <param name="when">Condition in which the CSS Class is added.</param>
/// <returns>CssBuilder</returns>
public CssBuilder AddStyle(CssBuilder builder, Func<bool> when) => AddClass(builder, when());

/// <summary>
/// Adds a conditional css Style when it exists in a dictionary to the builder with space separator.
/// Null safe operation.
Expand All @@ -179,7 +133,7 @@ public CssBuilder AddStyleFromAttributes(IDictionary<string, object>? additional
{
if (additionalAttributes != null && additionalAttributes.TryGetValue("style", out var c))
{
var styleList = c?.ToString();
var styleList = Convert.ToString(c, CultureInfo.InvariantCulture);
AddClass(styleList);
}
return this;
Expand All @@ -189,5 +143,5 @@ public CssBuilder AddStyleFromAttributes(IDictionary<string, object>? additional
/// Finalize the completed CSS Classes as a string.
/// </summary>
/// <returns>string</returns>
public string? Build() => stringBuffer.Count > 0 ? string.Join(" ", stringBuffer) : null;
public string? Build() => _hasConent ? _builder.ToString() : null;
Copy link

Copilot AI Sep 28, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The field name _hasConent has a spelling error. It should be _hasContent.

Copilot uses AI. Check for mistakes.
}
8 changes: 4 additions & 4 deletions test/UnitTest/Components/DrawerTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,13 @@ public class DrawerTest : BootstrapBlazorTestBase
public void Width_Ok()
{
var cut = Context.RenderComponent<Drawer>(builder => builder.Add(a => a.Width, "100px"));
Assert.Contains("width: 100px", cut.Markup);
Assert.Contains("--bb-drawer-width: 100px;", cut.Markup);

cut.SetParametersAndRender(pb =>
{
pb.Add(a => a.Width, "");
});
Assert.DoesNotContain("width:", cut.Markup);
Assert.DoesNotContain("--bb-drawer-width", cut.Markup);
}

[Fact]
Expand All @@ -28,13 +28,13 @@ public void Height_Ok()
builder.Add(a => a.Height, "100px");
builder.Add(a => a.Placement, Placement.Top);
});
Assert.Contains("height: 100px", cut.Markup);
Assert.Contains("--bb-drawer-height: 100px", cut.Markup);

cut.SetParametersAndRender(pb =>
{
pb.Add(a => a.Height, "");
});
Assert.DoesNotContain("height:", cut.Markup);
Assert.DoesNotContain("--bb-drawer-height:", cut.Markup);
}

[Fact]
Expand Down
Loading
Loading